From d91f7ab817d7dae37c80b769ee7472ef0b840d04 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Fri, 30 Jun 2017 11:38:34 +0300 Subject: [PATCH] Merge with upstream 0bdb20fd8e8614f74bd5bd8585ec3685ee8511be # Conflicts: # .appveyor.yml # .bash_helpers.sh # .travis.yml # CMake/Modules/CheckCompilerToolchain.cmake # CMake/Modules/FindDirectX.cmake # CMake/Modules/FindUrho3D.cmake # CMake/Modules/UrhoCommon.cmake # CMakeLists.txt # Docs/AngelScriptAPI.h # Docs/Doxyfile.in # Docs/GettingStarted.dox # Docs/LuaScriptAPI.dox # Docs/Reference.dox # Docs/ScriptAPI.dox # Docs/Urho3D.dox # README.md # Rakefile # Resources/EditorData/AtomicEditor/eulas/atomic_thirdparty_eula.txt # Source/Atomic/Atomic2D/ParticleEmitter2D.cpp # Source/Atomic/Atomic2D/PhysicsWorld2D.cpp # Source/Atomic/Atomic2D/SpriteSheet2D.cpp # Source/Atomic/Atomic2D/TmxFile2D.cpp # Source/Atomic/Audio/Sound.h # Source/Atomic/Core/Context.cpp # Source/Atomic/Core/Main.h # Source/Atomic/Core/ProcessUtils.cpp # Source/Atomic/Core/ProcessUtils.h # Source/Atomic/Engine/Application.cpp # Source/Atomic/Engine/Application.h # Source/Atomic/Engine/Engine.cpp # Source/Atomic/Graphics/Animation.h # Source/Atomic/Graphics/Model.cpp # Source/Atomic/Graphics/Model.h # Source/Atomic/Graphics/Text3D/Text3D.cpp # Source/Atomic/Graphics/Text3D/Text3D.h # Source/Atomic/Graphics/Text3D/Text3DBatch.cpp # Source/Atomic/Graphics/Text3D/Text3DBatch.h # Source/Atomic/Graphics/Text3D/Text3DBitmap.cpp # Source/Atomic/Graphics/Text3D/Text3DFont.cpp # Source/Atomic/Graphics/Text3D/Text3DFont.h # Source/Atomic/Graphics/Text3D/Text3DFontFace.cpp # Source/Atomic/Graphics/Text3D/Text3DFreeType.cpp # Source/Atomic/Graphics/Text3D/Text3DText.cpp # Source/Atomic/Graphics/Text3D/Text3DText.h # Source/Atomic/Graphics/Texture.h # Source/Atomic/Graphics/VertexBuffer.cpp # Source/Atomic/IO/Log.cpp # Source/Atomic/Physics/PhysicsWorld.cpp # Source/Atomic/Resource/JSONFile.cpp # Source/Atomic/Scene/Node.h # Source/CMakeLists.txt # Source/Samples/40_Localization/L10n.cpp # Source/Samples/42_PBRMaterials/PBRMaterials.cpp # Source/Samples/45_InverseKinematics/CMakeLists.txt # Source/ThirdParty/Civetweb/CMakeLists.txt # Source/ThirdParty/Lua/CMakeLists.txt # Source/ThirdParty/Lua/src/loslib.c # Source/ThirdParty/LuaJIT/CMakeLists.txt # Source/ThirdParty/LuaJIT/src/lj_arch.h # Source/ThirdParty/SQLite/CMakeLists.txt # Source/ThirdParty/boost/preprocessor/cat.hpp # Source/ThirdParty/boost/preprocessor/config/config.hpp # Source/ThirdParty/boost/preprocessor/seq/detail/binary_transform.hpp # Source/ThirdParty/boost/preprocessor/seq/to_list.hpp # Source/ThirdParty/rapidjson/include/rapidjson/internal/dtoa.h # Source/ThirdParty/rapidjson/include/rapidjson/internal/ieee754.h # Source/ThirdParty/rapidjson/include/rapidjson/internal/regex.h # Source/ThirdParty/rapidjson/include/rapidjson/internal/strtod.h # Source/ThirdParty/rapidjson/include/rapidjson/istreamwrapper.h # Source/ThirdParty/rapidjson/include/rapidjson/pointer.h # Source/ThirdParty/rapidjson/include/rapidjson/schema.h # Source/Tools/AssetImporter/AssetImporter.cpp # Source/Tools/CMakeLists.txt # Source/Tools/PackageTool/PackageTool.cpp # Source/Tools/Urho3DPlayer/CMakeLists.txt # Source/Tools/Urho3DPlayer/Urho3DPlayer.cpp # Source/Urho3D/.soversion # Source/Urho3D/AngelScript/APITemplates.h # Source/Urho3D/AngelScript/AudioAPI.cpp # Source/Urho3D/AngelScript/CoreAPI.cpp # Source/Urho3D/AngelScript/GraphicsAPI.cpp # Source/Urho3D/AngelScript/IKAPI.cpp # Source/Urho3D/AngelScript/IOAPI.cpp # Source/Urho3D/AngelScript/InputAPI.cpp # Source/Urho3D/AngelScript/MathAPI.cpp # Source/Urho3D/AngelScript/PhysicsAPI.cpp # Source/Urho3D/AngelScript/ResourceAPI.cpp # Source/Urho3D/AngelScript/ScriptAPI.h # Source/Urho3D/AngelScript/ScriptAPIDump.cpp # Source/Urho3D/AngelScript/ScriptFile.cpp # Source/Urho3D/AngelScript/UIAPI.cpp # Source/Urho3D/AngelScript/Urho2DAPI.cpp # Source/Urho3D/CMakeLists.txt # Source/Urho3D/LuaScript/pkgs/Audio/Sound.pkg # Source/Urho3D/LuaScript/pkgs/Audio/SoundSource.pkg # Source/Urho3D/LuaScript/pkgs/Core/ProcessUtils.pkg # Source/Urho3D/LuaScript/pkgs/Graphics/Animation.pkg # Source/Urho3D/LuaScript/pkgs/Graphics/Model.pkg # Source/Urho3D/LuaScript/pkgs/Graphics/Texture.pkg # Source/Urho3D/LuaScript/pkgs/Input/Input.pkg # Source/Urho3D/LuaScript/pkgs/Math/Quaternion.pkg # Source/Urho3D/LuaScript/pkgs/Math/Vector3.pkg # Source/Urho3D/LuaScript/pkgs/PhysicsLuaAPI.pkg # Source/Urho3D/LuaScript/pkgs/Resource/JSONValue.pkg # Source/Urho3D/LuaScript/pkgs/Resource/Resource.pkg # Source/Urho3D/LuaScript/pkgs/Scene/Node.pkg # Source/Urho3D/LuaScript/pkgs/UI/Font.pkg # Source/Urho3D/LuaScript/pkgs/UI/Text.pkg # Source/Urho3D/LuaScript/pkgs/UI/Text3D.pkg # Source/Urho3D/LuaScript/pkgs/UI/UI.pkg # Source/Urho3D/LuaScript/pkgs/Urho2D/ParticleEmitter2D.pkg # Source/Urho3D/UI/Cursor.cpp # Source/Urho3D/UI/UI.cpp # Source/Urho3D/UI/UI.h # Source/Urho3D/Urho2D/PhysicsEvents2D.h # bin/Autoload/LargeData/Materials/PBR/Check.xml # bin/Autoload/LargeData/Materials/PBR/HighRoughMetallic0.xml # bin/Autoload/LargeData/Materials/PBR/HighRoughMetallic10.xml # bin/Autoload/LargeData/Materials/PBR/HighRoughMetallic3.xml # bin/Autoload/LargeData/Materials/PBR/HighRoughMetallic5.xml # bin/Autoload/LargeData/Materials/PBR/HighRoughMetallic7.xml # bin/Autoload/LargeData/Materials/PBR/Metallic0.xml # bin/Autoload/LargeData/Materials/PBR/Metallic10.xml # bin/Autoload/LargeData/Materials/PBR/Metallic3.xml # bin/Autoload/LargeData/Materials/PBR/Metallic5.xml # bin/Autoload/LargeData/Materials/PBR/Metallic7.xml # bin/Autoload/LargeData/Materials/PBR/MetallicRough0.xml # bin/Autoload/LargeData/Materials/PBR/MetallicRough10.xml # bin/Autoload/LargeData/Materials/PBR/MetallicRough3.xml # bin/Autoload/LargeData/Materials/PBR/MetallicRough5.xml # bin/Autoload/LargeData/Materials/PBR/MetallicRough7.xml # bin/Autoload/LargeData/Materials/PBR/Mud.xml # bin/Autoload/LargeData/Materials/PBR/Roughness0.xml # bin/Autoload/LargeData/Materials/PBR/Roughness10.xml # bin/Autoload/LargeData/Materials/PBR/Roughness3.xml # bin/Autoload/LargeData/Materials/PBR/Roughness5.xml # bin/Autoload/LargeData/Materials/PBR/Roughness7.xml # bin/Autoload/LargeData/Materials/PBR/Tile.xml # bin/Data/LuaScripts/40_Localization.lua # bin/Data/LuaScripts/42_PBRMaterials.lua # bin/Data/Scenes/PBRExample.xml # bin/Data/Scripts/40_Localization.as # bin/Data/Scripts/42_PBRMaterials.as # bin/Data/Scripts/Editor.as # bin/Data/Scripts/Editor/EditorUI.as # bin/Data/Scripts/Editor/EditorView.as # cmake_generic.sh --- .gitignore | 1 + Build/CMake/Modules/AtomicMac.cmake | 2 +- CMake/Modules/PostProcessForWebModule.cmake | 35 + Resources/CoreData/Shaders/GLSL/BRDF.glsl | 43 +- .../CoreData/Shaders/GLSL/Constants.glsl | 2 +- Resources/CoreData/Shaders/GLSL/IBL.glsl | 16 +- Resources/CoreData/Shaders/GLSL/PBR.glsl | 110 +- Resources/CoreData/Shaders/HLSL/BRDF.hlsl | 43 +- .../CoreData/Shaders/HLSL/Constants.hlsl | 2 +- Resources/CoreData/Shaders/HLSL/IBL.hlsl | 16 +- Resources/CoreData/Shaders/HLSL/PBR.hlsl | 98 +- Script/Packages/Atomic/Resource.json | 2 +- Source/Atomic/Atomic2D/CollisionChain2D.cpp | 1 + Source/Atomic/Atomic2D/CollisionShape2D.cpp | 3 +- Source/Atomic/Atomic2D/ParticleEmitter2D.cpp | 25 +- Source/Atomic/Atomic2D/ParticleEmitter2D.h | 23 +- Source/Atomic/Atomic2D/PhysicsEvents2D.h | 18 +- Source/Atomic/Atomic2D/PhysicsWorld2D.cpp | 71 +- Source/Atomic/Atomic2D/PhysicsWorld2D.h | 14 +- Source/Atomic/Atomic2D/RigidBody2D.cpp | 20 +- Source/Atomic/Atomic2D/SpriteSheet2D.cpp | 4 +- Source/Atomic/Atomic2D/TmxFile2D.cpp | 11 + Source/Atomic/Audio/OggVorbisSoundStream.cpp | 10 + Source/Atomic/Audio/OggVorbisSoundStream.h | 3 + Source/Atomic/Audio/Sound.cpp | 8 +- Source/Atomic/Audio/Sound.h | 4 +- Source/Atomic/Audio/SoundSource.cpp | 24 + Source/Atomic/Audio/SoundSource.h | 2 + Source/Atomic/Audio/SoundStream.cpp | 5 + Source/Atomic/Audio/SoundStream.h | 3 + Source/Atomic/Core/Context.cpp | 4 +- Source/Atomic/Core/Main.h | 4 +- Source/Atomic/Core/ProcessUtils.cpp | 246 +- Source/Atomic/Core/ProcessUtils.h | 11 +- Source/Atomic/Engine/Application.cpp | 12 +- Source/Atomic/Engine/Application.h | 4 +- Source/Atomic/Engine/Engine.cpp | 15 +- Source/Atomic/Engine/Engine.h | 2 +- Source/Atomic/Graphics/AnimatedModel.cpp | 6 +- Source/Atomic/Graphics/Animation.cpp | 42 +- Source/Atomic/Graphics/Animation.h | 8 +- .../Graphics/Direct3D11/D3D11Graphics.cpp | 13 +- .../Graphics/Direct3D9/D3D9Graphics.cpp | 9 +- Source/Atomic/Graphics/Graphics.cpp | 2 +- Source/Atomic/Graphics/GraphicsDefs.h | 2 +- Source/Atomic/Graphics/Model.cpp | 55 +- Source/Atomic/Graphics/Model.h | 4 +- Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp | 30 +- .../Atomic/Graphics/OpenGL/OGLGraphicsImpl.h | 4 +- .../Atomic/Graphics/OpenGL/OGLTexture2D.cpp | 4 +- .../Atomic/Graphics/OpenGL/OGLTextureCube.cpp | 4 +- Source/Atomic/Graphics/Text3D/Text3D.cpp | 14 +- Source/Atomic/Graphics/Text3D/Text3D.h | 12 +- Source/Atomic/Graphics/Text3D/Text3DBatch.cpp | 58 +- Source/Atomic/Graphics/Text3D/Text3DBatch.h | 4 +- .../Atomic/Graphics/Text3D/Text3DBitmap.cpp | 6 +- Source/Atomic/Graphics/Text3D/Text3DBitmap.h | 2 +- Source/Atomic/Graphics/Text3D/Text3DFont.cpp | 35 +- Source/Atomic/Graphics/Text3D/Text3DFont.h | 8 +- .../Atomic/Graphics/Text3D/Text3DFontFace.cpp | 4 +- .../Atomic/Graphics/Text3D/Text3DFontFace.h | 16 +- .../Atomic/Graphics/Text3D/Text3DFreeType.cpp | 60 +- .../Atomic/Graphics/Text3D/Text3DFreeType.h | 30 +- Source/Atomic/Graphics/Text3D/Text3DText.cpp | 48 +- Source/Atomic/Graphics/Text3D/Text3DText.h | 36 +- Source/Atomic/Graphics/Texture.cpp | 8 +- Source/Atomic/Graphics/Texture.h | 6 +- Source/Atomic/Graphics/VertexBuffer.cpp | 13 +- Source/Atomic/Graphics/VertexBuffer.h | 3 + Source/Atomic/Graphics/View.cpp | 10 +- Source/Atomic/Graphics/View.h | 2 + Source/Atomic/IK/IKSolver.cpp | 2 + Source/Atomic/IO/Compression.cpp | 4 +- Source/Atomic/IO/FileSystem.cpp | 14 +- Source/Atomic/IO/FileWatcher.cpp | 12 +- Source/Atomic/IO/FileWatcher.h | 2 +- Source/Atomic/IO/Log.cpp | 10 +- Source/Atomic/Input/Input.cpp | 8 +- Source/Atomic/Input/Input.h | 2 + Source/Atomic/Math/MathDefs.h | 11 +- Source/Atomic/Math/Matrix3.h | 21 +- Source/Atomic/Math/Matrix3x4.h | 20 + Source/Atomic/Math/Matrix4.h | 30 +- Source/Atomic/Math/Quaternion.cpp | 10 + Source/Atomic/Math/Quaternion.h | 4 + Source/Atomic/Math/Vector3.h | 15 + .../Navigation/DynamicNavigationMesh.cpp | 2 +- Source/Atomic/Physics/PhysicsWorld.cpp | 9 +- Source/Atomic/Physics/RaycastVehicle.cpp | 744 ++++ Source/Atomic/Physics/RaycastVehicle.h | 187 + Source/Atomic/Resource/JSONFile.cpp | 4 +- Source/Atomic/Resource/JSONValue.cpp | 5 +- Source/Atomic/Resource/Resource.cpp | 63 + Source/Atomic/Resource/Resource.h | 39 + Source/Atomic/Resource/ResourceCache.cpp | 2 +- Source/Atomic/Resource/ResourceCache.h | 4 +- Source/Atomic/Scene/Node.cpp | 19 +- Source/Atomic/Scene/Node.h | 3 + Source/Atomic/Scene/ValueAnimationInfo.h | 3 + Source/AtomicNET/NETNative/CMakeLists.txt | 2 +- Source/ThirdParty/Bullet/AUTHORS.txt | 1 + Source/ThirdParty/Bullet/README.md | 49 +- Source/ThirdParty/Bullet/VERSION | 2 +- .../BroadphaseCollision/btAxisSweep3.h | 13 +- .../btBroadphaseInterface.h | 2 +- .../BroadphaseCollision/btBroadphaseProxy.h | 13 +- .../BroadphaseCollision/btDbvt.h | 132 +- .../BroadphaseCollision/btDbvtBroadphase.cpp | 32 +- .../BroadphaseCollision/btDbvtBroadphase.h | 5 +- .../BroadphaseCollision/btDispatcher.h | 8 +- .../btMultiSapBroadphase.cpp | 489 --- .../btMultiSapBroadphase.h | 151 - .../btOverlappingPairCache.cpp | 5 +- .../btOverlappingPairCache.h | 6 +- .../BroadphaseCollision/btQuantizedBvh.cpp | 2 + .../BroadphaseCollision/btQuantizedBvh.h | 2 +- .../btSimpleBroadphase.cpp | 4 +- .../BroadphaseCollision/btSimpleBroadphase.h | 6 +- .../SphereTriangleDetector.cpp | 77 +- .../btCollisionConfiguration.h | 3 + .../btCollisionDispatcher.cpp | 56 +- .../CollisionDispatch/btCollisionDispatcher.h | 8 +- .../CollisionDispatch/btCollisionObject.cpp | 7 + .../CollisionDispatch/btCollisionObject.h | 104 +- .../CollisionDispatch/btCollisionWorld.cpp | 165 +- .../CollisionDispatch/btCollisionWorld.h | 22 +- .../btCollisionWorldImporter.cpp | 4 +- .../btCompoundCollisionAlgorithm.cpp | 48 +- .../btCompoundCollisionAlgorithm.h | 4 + .../btCompoundCompoundCollisionAlgorithm.cpp | 60 +- .../btConvex2dConvex2dAlgorithm.cpp | 8 +- .../btConvex2dConvex2dAlgorithm.h | 3 - .../btConvexConcaveCollisionAlgorithm.cpp | 24 +- .../btConvexConcaveCollisionAlgorithm.h | 18 +- .../btConvexConvexAlgorithm.cpp | 69 +- .../btConvexConvexAlgorithm.h | 11 +- .../btDefaultCollisionConfiguration.cpp | 90 +- .../btDefaultCollisionConfiguration.h | 11 +- .../btHashedSimplePairCache.cpp | 4 +- .../btHashedSimplePairCache.h | 4 +- .../btInternalEdgeUtility.cpp | 6 +- .../CollisionDispatch/btManifoldResult.cpp | 43 +- .../CollisionDispatch/btManifoldResult.h | 12 +- .../btSphereSphereCollisionAlgorithm.cpp | 3 +- .../btSphereTriangleCollisionAlgorithm.cpp | 2 +- .../btBvhTriangleMeshShape.cpp | 9 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 4 + .../CollisionShapes/btCapsuleShape.cpp | 26 +- .../CollisionShapes/btCapsuleShape.h | 24 +- .../CollisionShapes/btCollisionShape.h | 2 +- .../CollisionShapes/btConeShape.h | 9 + .../CollisionShapes/btConvexHullShape.cpp | 17 +- .../CollisionShapes/btConvexHullShape.h | 5 +- .../CollisionShapes/btConvexPolyhedron.cpp | 3 +- .../CollisionShapes/btConvexShape.cpp | 10 +- .../CollisionShapes/btMultiSphereShape.cpp | 4 +- .../btMultimaterialTriangleMeshShape.h | 1 - .../Gimpact/btGImpactCollisionAlgorithm.h | 2 +- .../Gimpact/btGImpactShape.cpp | 53 + .../BulletCollision/Gimpact/btGImpactShape.h | 28 +- .../NarrowPhaseCollision/btGjkEpa2.cpp | 39 +- .../btGjkPairDetector.cpp | 58 +- .../NarrowPhaseCollision/btManifoldPoint.h | 55 +- .../btPersistentManifold.h | 11 +- .../btPolyhedralContactClipping.cpp | 12 +- .../btPolyhedralContactClipping.h | 7 +- .../btVoronoiSimplexSolver.cpp | 3 + .../btVoronoiSimplexSolver.h | 6 +- .../btCharacterControllerInterface.h | 2 +- .../btKinematicCharacterController.cpp | 472 ++- .../btKinematicCharacterController.h | 60 +- .../btConeTwistConstraint.cpp | 2 +- .../ConstraintSolver/btConeTwistConstraint.h | 66 +- .../ConstraintSolver/btContactSolverInfo.h | 5 +- .../btGeneric6DofConstraint.h | 27 +- .../btGeneric6DofSpring2Constraint.h | 16 +- .../btGeneric6DofSpringConstraint.h | 20 + .../ConstraintSolver/btHingeConstraint.h | 37 +- .../btPoint2PointConstraint.h | 5 + .../btSequentialImpulseConstraintSolver.cpp | 264 +- .../btSequentialImpulseConstraintSolver.h | 20 +- .../ConstraintSolver/btSliderConstraint.h | 7 + .../ConstraintSolver/btTypedConstraint.h | 6 +- .../Dynamics/btDiscreteDynamicsWorld.cpp | 75 +- .../Dynamics/btDiscreteDynamicsWorld.h | 11 +- .../Dynamics/btDiscreteDynamicsWorldMt.cpp | 162 + .../Dynamics/btDiscreteDynamicsWorldMt.h | 42 + .../BulletDynamics/Dynamics/btDynamicsWorld.h | 5 +- .../BulletDynamics/Dynamics/btRigidBody.cpp | 9 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 3 + .../Dynamics/btSimpleDynamicsWorld.cpp | 2 +- .../Dynamics/btSimpleDynamicsWorld.h | 2 +- .../Dynamics/btSimulationIslandManagerMt.cpp | 641 ++++ .../Dynamics/btSimulationIslandManagerMt.h | 109 + .../Featherstone/btMultiBody.cpp | 806 +--- .../BulletDynamics/Featherstone/btMultiBody.h | 196 +- .../Featherstone/btMultiBodyConstraint.cpp | 696 ++-- .../Featherstone/btMultiBodyConstraint.h | 21 +- .../btMultiBodyConstraintSolver.cpp | 630 +++- .../btMultiBodyConstraintSolver.h | 19 +- .../Featherstone/btMultiBodyDynamicsWorld.cpp | 94 +- .../Featherstone/btMultiBodyDynamicsWorld.h | 12 +- .../btMultiBodyFixedConstraint.cpp | 211 ++ .../Featherstone/btMultiBodyFixedConstraint.h | 94 + .../btMultiBodyJointLimitConstraint.cpp | 5 +- .../Featherstone/btMultiBodyJointMotor.cpp | 37 +- .../Featherstone/btMultiBodyJointMotor.h | 28 +- .../Featherstone/btMultiBodyLink.h | 25 +- .../Featherstone/btMultiBodyPoint2Point.cpp | 2 +- .../Featherstone/btMultiBodyPoint2Point.h | 7 +- .../btMultiBodySliderConstraint.cpp | 230 ++ .../btMultiBodySliderConstraint.h | 105 + .../MLCPSolvers/btMLCPSolver.cpp | 21 +- .../BulletDynamics/MLCPSolvers/btMLCPSolver.h | 21 +- .../MLCPSolvers/btSolveProjectedGaussSeidel.h | 30 +- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 2 - .../Bullet/src/BulletSoftBody/btSoftBody.cpp | 55 +- .../Bullet/src/BulletSoftBody/btSoftBody.h | 7 +- .../btSoftBodyConcaveCollisionAlgorithm.cpp | 7 +- .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 4 +- .../src/BulletSoftBody/btSoftBodyInternals.h | 39 +- .../btSoftMultiBodyDynamicsWorld.cpp | 367 ++ .../btSoftMultiBodyDynamicsWorld.h | 108 + .../btSoftRigidCollisionAlgorithm.h | 4 +- .../btSoftRigidDynamicsWorld.cpp | 2 +- .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 2 +- .../btSoftSoftCollisionAlgorithm.h | 4 +- .../Bullet/src/BulletSoftBody/btSparseSDF.h | 2 +- .../src/LinearMath/btAlignedAllocator.cpp | 114 +- .../src/LinearMath/btAlignedAllocator.h | 8 +- .../src/LinearMath/btAlignedObjectArray.h | 31 +- .../Bullet/src/LinearMath/btConvexHull.cpp | 4 +- .../Bullet/src/LinearMath/btHashMap.h | 17 + .../Bullet/src/LinearMath/btIDebugDraw.h | 6 +- .../Bullet/src/LinearMath/btMatrix3x3.h | 7 +- .../Bullet/src/LinearMath/btMatrixX.h | 3 - .../src/LinearMath/btPolarDecomposition.cpp | 3 +- .../src/LinearMath/btPolarDecomposition.h | 7 +- .../Bullet/src/LinearMath/btPoolAllocator.h | 15 +- .../Bullet/src/LinearMath/btQuaternion.h | 45 +- .../Bullet/src/LinearMath/btQuickprof.cpp | 335 +- .../Bullet/src/LinearMath/btQuickprof.h | 94 +- .../Bullet/src/LinearMath/btScalar.h | 16 +- .../Bullet/src/LinearMath/btSerializer.cpp | 1988 +++++----- .../Bullet/src/LinearMath/btSerializer.h | 26 +- .../Bullet/src/LinearMath/btThreads.cpp | 231 ++ .../Bullet/src/LinearMath/btThreads.h | 75 + .../Bullet/src/LinearMath/btTransform.h | 4 +- .../Bullet/src/LinearMath/btVector3.cpp | 2 +- .../Bullet/src/LinearMath/btVector3.h | 29 +- .../Bullet/src/btBulletCollisionCommon.h | 1 - Source/ThirdParty/Civetweb/CMakeLists.txt | 10 +- Source/ThirdParty/FreeType/README | 12 +- Source/ThirdParty/FreeType/docs/CHANGES | 133 +- Source/ThirdParty/FreeType/docs/CUSTOMIZE | 2 +- Source/ThirdParty/FreeType/docs/DEBUG | 4 +- Source/ThirdParty/FreeType/docs/INSTALL | 4 +- Source/ThirdParty/FreeType/docs/INSTALL.ANY | 2 +- Source/ThirdParty/FreeType/docs/INSTALL.CROSS | 2 +- Source/ThirdParty/FreeType/docs/INSTALL.GNU | 2 +- Source/ThirdParty/FreeType/docs/INSTALL.MAC | 42 +- Source/ThirdParty/FreeType/docs/INSTALL.UNIX | 5 +- Source/ThirdParty/FreeType/docs/INSTALL.VMS | 2 +- Source/ThirdParty/FreeType/docs/TODO | 2 +- Source/ThirdParty/FreeType/docs/VERSION.DLL | 123 - Source/ThirdParty/FreeType/docs/VERSIONS.TXT | 3 +- Source/ThirdParty/FreeType/docs/formats.txt | 18 +- .../FreeType/docs/freetype-config.1 | 146 + Source/ThirdParty/FreeType/docs/raster.txt | 2 +- Source/ThirdParty/FreeType/docs/release | 2 +- .../include/freetype/config/ftconfig.h | 11 +- .../include/freetype/config/ftheader.h | 15 +- .../include/freetype/config/ftoption.h | 80 +- .../include/freetype/config/ftstdlib.h | 2 +- .../FreeType/include/freetype/freetype.h | 1001 +++-- .../FreeType/include/freetype/ftadvanc.h | 2 +- .../FreeType/include/freetype/ftautoh.h | 28 +- .../FreeType/include/freetype/ftbbox.h | 2 +- .../FreeType/include/freetype/ftbdf.h | 2 +- .../FreeType/include/freetype/ftbitmap.h | 2 +- .../FreeType/include/freetype/ftbzip2.h | 2 +- .../FreeType/include/freetype/ftcache.h | 2 +- .../FreeType/include/freetype/ftcffdrv.h | 48 +- .../FreeType/include/freetype/ftchapters.h | 1 + .../FreeType/include/freetype/ftcid.h | 2 +- .../FreeType/include/freetype/fterrdef.h | 4 +- .../FreeType/include/freetype/fterrors.h | 4 +- .../FreeType/include/freetype/ftfntfmt.h | 2 +- .../FreeType/include/freetype/ftgasp.h | 16 +- .../FreeType/include/freetype/ftglyph.h | 4 +- .../FreeType/include/freetype/ftgxval.h | 2 +- .../FreeType/include/freetype/ftgzip.h | 2 +- .../FreeType/include/freetype/ftimage.h | 4 +- .../FreeType/include/freetype/ftincrem.h | 2 +- .../FreeType/include/freetype/ftlcdfil.h | 37 +- .../FreeType/include/freetype/ftlist.h | 2 +- .../FreeType/include/freetype/ftlzw.h | 2 +- .../FreeType/include/freetype/ftmac.h | 2 +- .../FreeType/include/freetype/ftmm.h | 145 +- .../FreeType/include/freetype/ftmodapi.h | 49 +- .../FreeType/include/freetype/ftmoderr.h | 2 +- .../FreeType/include/freetype/ftotval.h | 2 +- .../FreeType/include/freetype/ftoutln.h | 2 +- .../FreeType/include/freetype/ftpcfdrv.h | 105 + .../FreeType/include/freetype/ftpfr.h | 2 +- .../FreeType/include/freetype/ftrender.h | 2 +- .../FreeType/include/freetype/ftsizes.h | 2 +- .../FreeType/include/freetype/ftsnames.h | 147 +- .../FreeType/include/freetype/ftstroke.h | 4 +- .../FreeType/include/freetype/ftsynth.h | 2 +- .../FreeType/include/freetype/ftsystem.h | 2 +- .../FreeType/include/freetype/fttrigon.h | 2 +- .../FreeType/include/freetype/ftttdrv.h | 11 +- .../FreeType/include/freetype/fttypes.h | 2 +- .../FreeType/include/freetype/ftwinfnt.h | 2 +- .../FreeType/include/freetype/ftxf86.h | 83 - .../include/freetype/internal/autohint.h | 2 +- .../include/freetype/internal/ftcalc.h | 2 +- .../include/freetype/internal/ftdebug.h | 2 +- .../include/freetype/internal/ftdriver.h | 2 +- .../include/freetype/internal/ftgloadr.h | 2 +- .../include/freetype/internal/ftmemory.h | 2 +- .../include/freetype/internal/ftobjs.h | 68 +- .../include/freetype/internal/ftpic.h | 2 +- .../include/freetype/internal/ftrfork.h | 2 +- .../include/freetype/internal/ftserv.h | 88 +- .../include/freetype/internal/ftstream.h | 4 +- .../include/freetype/internal/fttrace.h | 2 +- .../include/freetype/internal/ftvalid.h | 2 +- .../include/freetype/internal/internal.h | 2 +- .../include/freetype/internal/psaux.h | 4 +- .../include/freetype/internal/pshints.h | 2 +- .../freetype/internal/services/svbdf.h | 2 +- .../freetype/internal/services/svcid.h | 2 +- .../freetype/internal/services/svfntfmt.h | 2 +- .../freetype/internal/services/svgldict.h | 2 +- .../freetype/internal/services/svgxval.h | 2 +- .../freetype/internal/services/svkern.h | 2 +- .../freetype/internal/services/svmetric.h | 10 +- .../include/freetype/internal/services/svmm.h | 3 +- .../freetype/internal/services/svotval.h | 2 +- .../freetype/internal/services/svpfr.h | 2 +- .../freetype/internal/services/svpostnm.h | 2 +- .../freetype/internal/services/svprop.h | 2 +- .../freetype/internal/services/svpscmap.h | 2 +- .../freetype/internal/services/svpsinfo.h | 2 +- .../freetype/internal/services/svsfnt.h | 2 +- .../freetype/internal/services/svttcmap.h | 2 +- .../freetype/internal/services/svtteng.h | 2 +- .../freetype/internal/services/svttglyf.h | 2 +- .../freetype/internal/services/svwinfnt.h | 2 +- .../freetype/internal/services/svxf86nm.h | 55 - .../FreeType/include/freetype/internal/sfnt.h | 42 +- .../include/freetype/internal/t1types.h | 2 +- .../include/freetype/internal/tttypes.h | 138 +- .../FreeType/include/freetype/t1tables.h | 6 +- .../FreeType/include/freetype/ttnameid.h | 627 ++-- .../FreeType/include/freetype/tttables.h | 363 +- .../FreeType/include/freetype/tttags.h | 2 +- .../FreeType/include/freetype/ttunpat.h | 4 +- Source/ThirdParty/FreeType/include/ft2build.h | 2 +- .../FreeType/src/autofit/afangles.c | 2 +- .../ThirdParty/FreeType/src/autofit/afblue.c | 282 +- .../FreeType/src/autofit/afblue.cin | 2 +- .../FreeType/src/autofit/afblue.dat | 358 +- .../ThirdParty/FreeType/src/autofit/afblue.h | 370 +- .../FreeType/src/autofit/afblue.hin | 2 +- .../ThirdParty/FreeType/src/autofit/afcjk.c | 10 +- .../ThirdParty/FreeType/src/autofit/afcjk.h | 2 +- .../ThirdParty/FreeType/src/autofit/afcover.h | 2 +- .../ThirdParty/FreeType/src/autofit/afdummy.c | 2 +- .../ThirdParty/FreeType/src/autofit/afdummy.h | 2 +- .../FreeType/src/autofit/aferrors.h | 2 +- .../FreeType/src/autofit/afglobal.c | 5 +- .../FreeType/src/autofit/afglobal.h | 2 +- .../ThirdParty/FreeType/src/autofit/afhints.c | 2 +- .../ThirdParty/FreeType/src/autofit/afhints.h | 2 +- .../ThirdParty/FreeType/src/autofit/afindic.c | 4 +- .../ThirdParty/FreeType/src/autofit/afindic.h | 2 +- .../ThirdParty/FreeType/src/autofit/aflatin.c | 115 +- .../ThirdParty/FreeType/src/autofit/aflatin.h | 2 +- .../FreeType/src/autofit/aflatin2.c | 22 +- .../FreeType/src/autofit/aflatin2.h | 2 +- .../FreeType/src/autofit/afloader.c | 117 +- .../FreeType/src/autofit/afloader.h | 2 +- .../FreeType/src/autofit/afmodule.c | 23 +- .../FreeType/src/autofit/afmodule.h | 2 +- .../ThirdParty/FreeType/src/autofit/afpic.c | 2 +- .../ThirdParty/FreeType/src/autofit/afpic.h | 4 +- .../FreeType/src/autofit/afranges.c | 382 +- .../FreeType/src/autofit/afranges.h | 2 +- .../FreeType/src/autofit/afscript.h | 159 +- .../FreeType/src/autofit/afshaper.c | 2 +- .../FreeType/src/autofit/afshaper.h | 2 +- .../FreeType/src/autofit/afstyles.h | 178 +- .../ThirdParty/FreeType/src/autofit/aftypes.h | 3 +- .../ThirdParty/FreeType/src/autofit/afwarp.c | 3 +- .../ThirdParty/FreeType/src/autofit/afwarp.h | 2 +- .../FreeType/src/autofit/afwrtsys.h | 2 +- .../ThirdParty/FreeType/src/autofit/autofit.c | 25 +- Source/ThirdParty/FreeType/src/base/basepic.c | 2 +- Source/ThirdParty/FreeType/src/base/basepic.h | 2 +- .../ThirdParty/FreeType/src/base/ftadvanc.c | 2 +- Source/ThirdParty/FreeType/src/base/ftapi.c | 4 +- Source/ThirdParty/FreeType/src/base/ftbase.c | 9 +- Source/ThirdParty/FreeType/src/base/ftbase.h | 2 +- Source/ThirdParty/FreeType/src/base/ftbbox.c | 2 +- Source/ThirdParty/FreeType/src/base/ftbdf.c | 2 +- .../ThirdParty/FreeType/src/base/ftbitmap.c | 2 +- Source/ThirdParty/FreeType/src/base/ftcalc.c | 2 +- Source/ThirdParty/FreeType/src/base/ftcid.c | 2 +- .../ThirdParty/FreeType/src/base/ftdbgmem.c | 2 +- Source/ThirdParty/FreeType/src/base/ftdebug.c | 2 +- .../ThirdParty/FreeType/src/base/ftfntfmt.c | 2 +- .../ThirdParty/FreeType/src/base/ftfstype.c | 2 +- Source/ThirdParty/FreeType/src/base/ftgasp.c | 2 +- .../ThirdParty/FreeType/src/base/ftgloadr.c | 2 +- Source/ThirdParty/FreeType/src/base/ftglyph.c | 2 +- Source/ThirdParty/FreeType/src/base/ftgxval.c | 4 +- Source/ThirdParty/FreeType/src/base/ftinit.c | 37 +- .../ThirdParty/FreeType/src/base/ftlcdfil.c | 54 +- Source/ThirdParty/FreeType/src/base/ftmac.c | 14 +- Source/ThirdParty/FreeType/src/base/ftmm.c | 88 +- Source/ThirdParty/FreeType/src/base/ftobjs.c | 144 +- Source/ThirdParty/FreeType/src/base/ftotval.c | 2 +- Source/ThirdParty/FreeType/src/base/ftoutln.c | 4 +- .../ThirdParty/FreeType/src/base/ftpatent.c | 4 +- Source/ThirdParty/FreeType/src/base/ftpfr.c | 2 +- Source/ThirdParty/FreeType/src/base/ftpic.c | 2 +- Source/ThirdParty/FreeType/src/base/ftrfork.c | 2 +- .../ThirdParty/FreeType/src/base/ftsnames.c | 58 +- .../ThirdParty/FreeType/src/base/ftstream.c | 2 +- .../ThirdParty/FreeType/src/base/ftstroke.c | 2 +- Source/ThirdParty/FreeType/src/base/ftsynth.c | 4 +- .../ThirdParty/FreeType/src/base/ftsystem.c | 2 +- .../ThirdParty/FreeType/src/base/fttrigon.c | 2 +- Source/ThirdParty/FreeType/src/base/fttype1.c | 2 +- Source/ThirdParty/FreeType/src/base/ftutil.c | 2 +- .../ThirdParty/FreeType/src/base/ftwinfnt.c | 2 +- Source/ThirdParty/FreeType/src/base/ftxf86.c | 40 - Source/ThirdParty/FreeType/src/bdf/bdf.c | 3 +- .../ThirdParty/FreeType/src/bzip2/ftbzip2.c | 2 +- .../ThirdParty/FreeType/src/cache/ftcache.c | 11 +- .../ThirdParty/FreeType/src/cache/ftcbasic.c | 2 +- .../ThirdParty/FreeType/src/cache/ftccache.c | 2 +- .../ThirdParty/FreeType/src/cache/ftccache.h | 2 +- .../ThirdParty/FreeType/src/cache/ftccback.h | 2 +- .../ThirdParty/FreeType/src/cache/ftccmap.c | 2 +- .../ThirdParty/FreeType/src/cache/ftcerror.h | 2 +- .../ThirdParty/FreeType/src/cache/ftcglyph.c | 2 +- .../ThirdParty/FreeType/src/cache/ftcglyph.h | 2 +- .../ThirdParty/FreeType/src/cache/ftcimage.c | 2 +- .../ThirdParty/FreeType/src/cache/ftcimage.h | 2 +- .../ThirdParty/FreeType/src/cache/ftcmanag.c | 2 +- .../ThirdParty/FreeType/src/cache/ftcmanag.h | 2 +- Source/ThirdParty/FreeType/src/cache/ftcmru.c | 2 +- Source/ThirdParty/FreeType/src/cache/ftcmru.h | 2 +- .../ThirdParty/FreeType/src/cache/ftcsbits.c | 2 +- .../ThirdParty/FreeType/src/cache/ftcsbits.h | 2 +- Source/ThirdParty/FreeType/src/cff/cf2error.h | 2 +- Source/ThirdParty/FreeType/src/cff/cf2ft.c | 13 +- Source/ThirdParty/FreeType/src/cff/cf2intrp.c | 205 +- Source/ThirdParty/FreeType/src/cff/cff.c | 10 +- Source/ThirdParty/FreeType/src/cff/cffcmap.c | 2 +- Source/ThirdParty/FreeType/src/cff/cffcmap.h | 2 +- Source/ThirdParty/FreeType/src/cff/cffdrivr.c | 85 +- Source/ThirdParty/FreeType/src/cff/cffdrivr.h | 2 +- Source/ThirdParty/FreeType/src/cff/cfferrs.h | 2 +- Source/ThirdParty/FreeType/src/cff/cffgload.c | 49 +- Source/ThirdParty/FreeType/src/cff/cffgload.h | 2 +- Source/ThirdParty/FreeType/src/cff/cffload.c | 169 +- Source/ThirdParty/FreeType/src/cff/cffload.h | 7 +- Source/ThirdParty/FreeType/src/cff/cffobjs.c | 117 +- Source/ThirdParty/FreeType/src/cff/cffobjs.h | 10 +- Source/ThirdParty/FreeType/src/cff/cffparse.c | 47 +- Source/ThirdParty/FreeType/src/cff/cffparse.h | 12 +- Source/ThirdParty/FreeType/src/cff/cffpic.c | 2 +- Source/ThirdParty/FreeType/src/cff/cffpic.h | 31 +- Source/ThirdParty/FreeType/src/cff/cfftoken.h | 2 +- Source/ThirdParty/FreeType/src/cff/cfftypes.h | 9 +- Source/ThirdParty/FreeType/src/cid/ciderrs.h | 2 +- Source/ThirdParty/FreeType/src/cid/cidgload.c | 2 +- Source/ThirdParty/FreeType/src/cid/cidgload.h | 2 +- Source/ThirdParty/FreeType/src/cid/cidload.c | 5 +- Source/ThirdParty/FreeType/src/cid/cidload.h | 2 +- Source/ThirdParty/FreeType/src/cid/cidobjs.c | 12 +- Source/ThirdParty/FreeType/src/cid/cidobjs.h | 2 +- Source/ThirdParty/FreeType/src/cid/cidparse.c | 2 +- Source/ThirdParty/FreeType/src/cid/cidparse.h | 2 +- Source/ThirdParty/FreeType/src/cid/cidriver.c | 2 +- Source/ThirdParty/FreeType/src/cid/cidriver.h | 2 +- Source/ThirdParty/FreeType/src/cid/cidtoken.h | 2 +- Source/ThirdParty/FreeType/src/cid/type1cid.c | 8 +- Source/ThirdParty/FreeType/src/gxvalid/README | 4 +- .../ThirdParty/FreeType/src/gxvalid/gxvalid.c | 16 +- .../ThirdParty/FreeType/src/gxvalid/gxvalid.h | 4 +- .../ThirdParty/FreeType/src/gxvalid/gxvbsln.c | 2 +- .../FreeType/src/gxvalid/gxvcommn.c | 4 +- .../FreeType/src/gxvalid/gxvcommn.h | 2 +- .../FreeType/src/gxvalid/gxverror.h | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvfeat.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvfeat.h | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvfgen.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvjust.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvkern.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvlcar.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvmod.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvmod.h | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvmort.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvmort.h | 2 +- .../FreeType/src/gxvalid/gxvmort0.c | 2 +- .../FreeType/src/gxvalid/gxvmort1.c | 2 +- .../FreeType/src/gxvalid/gxvmort2.c | 2 +- .../FreeType/src/gxvalid/gxvmort4.c | 2 +- .../FreeType/src/gxvalid/gxvmort5.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvmorx.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvmorx.h | 2 +- .../FreeType/src/gxvalid/gxvmorx0.c | 2 +- .../FreeType/src/gxvalid/gxvmorx1.c | 2 +- .../FreeType/src/gxvalid/gxvmorx2.c | 2 +- .../FreeType/src/gxvalid/gxvmorx4.c | 2 +- .../FreeType/src/gxvalid/gxvmorx5.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvopbd.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvprop.c | 2 +- .../ThirdParty/FreeType/src/gxvalid/gxvtrak.c | 2 +- Source/ThirdParty/FreeType/src/lzw/ftlzw.c | 2 +- Source/ThirdParty/FreeType/src/lzw/ftzopen.c | 2 +- Source/ThirdParty/FreeType/src/lzw/ftzopen.h | 2 +- .../ThirdParty/FreeType/src/otvalid/otvalid.c | 5 +- .../ThirdParty/FreeType/src/otvalid/otvalid.h | 2 +- .../ThirdParty/FreeType/src/otvalid/otvbase.c | 2 +- .../FreeType/src/otvalid/otvcommn.c | 2 +- .../FreeType/src/otvalid/otvcommn.h | 2 +- .../FreeType/src/otvalid/otverror.h | 2 +- .../ThirdParty/FreeType/src/otvalid/otvgdef.c | 2 +- .../ThirdParty/FreeType/src/otvalid/otvgpos.c | 2 +- .../ThirdParty/FreeType/src/otvalid/otvgpos.h | 2 +- .../ThirdParty/FreeType/src/otvalid/otvgsub.c | 2 +- .../ThirdParty/FreeType/src/otvalid/otvjstf.c | 2 +- .../ThirdParty/FreeType/src/otvalid/otvmath.c | 2 +- .../ThirdParty/FreeType/src/otvalid/otvmod.c | 2 +- .../ThirdParty/FreeType/src/otvalid/otvmod.h | 2 +- Source/ThirdParty/FreeType/src/pcf/pcf.c | 8 +- Source/ThirdParty/FreeType/src/pcf/pcf.h | 9 + Source/ThirdParty/FreeType/src/pcf/pcfdrivr.c | 172 +- Source/ThirdParty/FreeType/src/pcf/pcfread.c | 370 +- Source/ThirdParty/FreeType/src/pfr/pfr.c | 11 +- Source/ThirdParty/FreeType/src/pfr/pfrcmap.c | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrcmap.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrdrivr.c | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrdrivr.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrerror.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrgload.c | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrgload.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrload.c | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrload.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrobjs.c | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrobjs.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrsbit.c | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrsbit.h | 2 +- Source/ThirdParty/FreeType/src/pfr/pfrtypes.h | 2 +- .../ThirdParty/FreeType/src/psaux/afmparse.c | 11 +- .../ThirdParty/FreeType/src/psaux/afmparse.h | 2 +- Source/ThirdParty/FreeType/src/psaux/psaux.c | 14 +- .../ThirdParty/FreeType/src/psaux/psauxerr.h | 2 +- .../ThirdParty/FreeType/src/psaux/psauxmod.c | 2 +- .../ThirdParty/FreeType/src/psaux/psauxmod.h | 2 +- Source/ThirdParty/FreeType/src/psaux/psconv.c | 2 +- Source/ThirdParty/FreeType/src/psaux/psconv.h | 2 +- Source/ThirdParty/FreeType/src/psaux/psobjs.c | 12 +- Source/ThirdParty/FreeType/src/psaux/psobjs.h | 2 +- Source/ThirdParty/FreeType/src/psaux/t1cmap.c | 2 +- Source/ThirdParty/FreeType/src/psaux/t1cmap.h | 2 +- .../ThirdParty/FreeType/src/psaux/t1decode.c | 15 +- .../ThirdParty/FreeType/src/psaux/t1decode.h | 2 +- .../FreeType/src/pshinter/pshalgo.c | 2 +- .../FreeType/src/pshinter/pshalgo.h | 2 +- .../FreeType/src/pshinter/pshglob.c | 2 +- .../FreeType/src/pshinter/pshglob.h | 2 +- .../FreeType/src/pshinter/pshinter.c | 10 +- .../ThirdParty/FreeType/src/pshinter/pshmod.c | 2 +- .../ThirdParty/FreeType/src/pshinter/pshmod.h | 2 +- .../FreeType/src/pshinter/pshnterr.h | 2 +- .../ThirdParty/FreeType/src/pshinter/pshpic.c | 2 +- .../ThirdParty/FreeType/src/pshinter/pshpic.h | 2 +- .../ThirdParty/FreeType/src/pshinter/pshrec.c | 2 +- .../ThirdParty/FreeType/src/pshinter/pshrec.h | 2 +- .../FreeType/src/psnames/psmodule.c | 3 +- .../FreeType/src/psnames/psmodule.h | 2 +- .../FreeType/src/psnames/psnamerr.h | 2 +- .../ThirdParty/FreeType/src/psnames/psnames.c | 6 +- .../ThirdParty/FreeType/src/psnames/pspic.c | 2 +- .../ThirdParty/FreeType/src/psnames/pspic.h | 2 +- .../FreeType/src/psnames/pstables.h | 4 +- .../ThirdParty/FreeType/src/raster/ftmisc.h | 2 +- .../ThirdParty/FreeType/src/raster/ftraster.c | 2 +- .../ThirdParty/FreeType/src/raster/ftraster.h | 2 +- .../ThirdParty/FreeType/src/raster/ftrend1.c | 2 +- .../ThirdParty/FreeType/src/raster/ftrend1.h | 2 +- .../ThirdParty/FreeType/src/raster/raster.c | 6 +- .../ThirdParty/FreeType/src/raster/rasterrs.h | 2 +- .../ThirdParty/FreeType/src/raster/rastpic.c | 2 +- .../ThirdParty/FreeType/src/raster/rastpic.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/pngshim.c | 14 +- Source/ThirdParty/FreeType/src/sfnt/pngshim.h | 2 +- .../ThirdParty/FreeType/src/sfnt/sfdriver.c | 864 ++++- .../ThirdParty/FreeType/src/sfnt/sfdriver.h | 2 +- .../ThirdParty/FreeType/src/sfnt/sferrors.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/sfnt.c | 26 +- Source/ThirdParty/FreeType/src/sfnt/sfntpic.c | 2 +- Source/ThirdParty/FreeType/src/sfnt/sfntpic.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/sfobjs.c | 204 +- Source/ThirdParty/FreeType/src/sfnt/sfobjs.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttbdf.c | 9 +- Source/ThirdParty/FreeType/src/sfnt/ttbdf.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttcmap.c | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttcmap.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttcmapc.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttkern.c | 9 +- Source/ThirdParty/FreeType/src/sfnt/ttkern.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttload.c | 145 +- Source/ThirdParty/FreeType/src/sfnt/ttload.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttmtx.c | 10 +- Source/ThirdParty/FreeType/src/sfnt/ttmtx.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttpost.c | 13 +- Source/ThirdParty/FreeType/src/sfnt/ttpost.h | 2 +- Source/ThirdParty/FreeType/src/sfnt/ttsbit.c | 18 +- Source/ThirdParty/FreeType/src/sfnt/ttsbit.h | 2 +- .../ThirdParty/FreeType/src/smooth/ftgrays.c | 95 +- .../ThirdParty/FreeType/src/smooth/ftgrays.h | 2 +- .../ThirdParty/FreeType/src/smooth/ftsmerrs.h | 2 +- .../ThirdParty/FreeType/src/smooth/ftsmooth.c | 79 +- .../ThirdParty/FreeType/src/smooth/ftsmooth.h | 11 +- .../ThirdParty/FreeType/src/smooth/ftspic.c | 2 +- .../ThirdParty/FreeType/src/smooth/ftspic.h | 2 +- .../ThirdParty/FreeType/src/smooth/smooth.c | 6 +- .../FreeType/src/truetype/truetype.c | 18 +- .../FreeType/src/truetype/ttdriver.c | 32 +- .../FreeType/src/truetype/ttdriver.h | 2 +- .../FreeType/src/truetype/tterrors.h | 2 +- .../FreeType/src/truetype/ttgload.c | 192 +- .../FreeType/src/truetype/ttgload.h | 2 +- .../FreeType/src/truetype/ttgxvar.c | 1835 ++++++--- .../FreeType/src/truetype/ttgxvar.h | 239 +- .../FreeType/src/truetype/ttinterp.c | 173 +- .../FreeType/src/truetype/ttinterp.h | 14 +- .../ThirdParty/FreeType/src/truetype/ttobjs.c | 184 +- .../ThirdParty/FreeType/src/truetype/ttobjs.h | 8 +- .../ThirdParty/FreeType/src/truetype/ttpic.c | 2 +- .../ThirdParty/FreeType/src/truetype/ttpic.h | 2 +- .../FreeType/src/truetype/ttpload.c | 2 +- .../FreeType/src/truetype/ttpload.h | 2 +- .../FreeType/src/truetype/ttsubpix.c | 13 +- .../FreeType/src/truetype/ttsubpix.h | 2 +- Source/ThirdParty/FreeType/src/type1/t1afm.c | 11 +- Source/ThirdParty/FreeType/src/type1/t1afm.h | 2 +- .../ThirdParty/FreeType/src/type1/t1driver.c | 2 +- .../ThirdParty/FreeType/src/type1/t1driver.h | 2 +- .../ThirdParty/FreeType/src/type1/t1errors.h | 2 +- .../ThirdParty/FreeType/src/type1/t1gload.c | 2 +- .../ThirdParty/FreeType/src/type1/t1gload.h | 2 +- Source/ThirdParty/FreeType/src/type1/t1load.c | 2 +- Source/ThirdParty/FreeType/src/type1/t1load.h | 2 +- Source/ThirdParty/FreeType/src/type1/t1objs.c | 15 +- Source/ThirdParty/FreeType/src/type1/t1objs.h | 2 +- .../ThirdParty/FreeType/src/type1/t1parse.c | 2 +- .../ThirdParty/FreeType/src/type1/t1parse.h | 2 +- .../ThirdParty/FreeType/src/type1/t1tokens.h | 2 +- Source/ThirdParty/FreeType/src/type1/type1.c | 15 +- .../ThirdParty/FreeType/src/type42/t42drivr.c | 2 +- .../ThirdParty/FreeType/src/type42/t42drivr.h | 2 +- .../ThirdParty/FreeType/src/type42/t42error.h | 2 +- .../ThirdParty/FreeType/src/type42/t42objs.c | 2 +- .../ThirdParty/FreeType/src/type42/t42objs.h | 2 +- .../ThirdParty/FreeType/src/type42/t42parse.c | 2 +- .../ThirdParty/FreeType/src/type42/t42parse.h | 2 +- .../ThirdParty/FreeType/src/type42/t42types.h | 2 +- .../ThirdParty/FreeType/src/type42/type42.c | 8 +- .../FreeType/src/winfonts/fnterrs.h | 2 +- .../ThirdParty/FreeType/src/winfonts/winfnt.c | 4 +- .../ThirdParty/FreeType/src/winfonts/winfnt.h | 2 +- Source/ThirdParty/LZ4/LICENSE | 24 + Source/ThirdParty/LZ4/lz4.c | 815 ++-- Source/ThirdParty/LZ4/lz4.h | 381 +- Source/ThirdParty/LZ4/lz4hc.c | 379 +- Source/ThirdParty/LZ4/lz4hc.h | 257 +- Source/ThirdParty/LZ4/lz4opt.h | 363 ++ Source/ThirdParty/SDL/CMakeLists.txt | 36 +- Source/ThirdParty/SDL/cmake/sdlchecks.cmake | 2 +- .../ThirdParty/SDL/include/SDL_config.h.cmake | 6 +- .../SDL/src/core/windows/SDL_xinput.h | 9 +- .../src/video/uikit/SDL_uikitappdelegate.m | 10 +- Source/ThirdParty/SQLite/CMakeLists.txt | 6 +- .../rapidjson/include/rapidjson/allocators.h | 384 +- .../rapidjson/include/rapidjson/document.h | 3343 +++++++++++++---- .../include/rapidjson/encodedstream.h | 427 ++- .../rapidjson/include/rapidjson/encodings.h | 1017 +++-- .../include/rapidjson/filereadstream.h | 127 +- .../rapidjson/include/rapidjson/filestream.h | 49 - .../include/rapidjson/filewritestream.h | 133 +- .../include/rapidjson/internal/dtoa.h | 8 +- .../include/rapidjson/internal/ieee754.h | 4 +- .../include/rapidjson/internal/pow10.h | 81 +- .../include/rapidjson/internal/regex.h | 211 +- .../include/rapidjson/internal/stack.h | 272 +- .../include/rapidjson/internal/strfunc.h | 65 +- .../include/rapidjson/internal/strtod.h | 14 +- .../include/rapidjson/istreamwrapper.h | 2 +- .../rapidjson/include/rapidjson/pointer.h | 12 +- .../include/rapidjson/prettywriter.h | 411 +- .../rapidjson/include/rapidjson/rapidjson.h | 674 +++- .../rapidjson/include/rapidjson/reader.h | 2676 ++++++++++--- .../rapidjson/include/rapidjson/schema.h | 86 +- .../include/rapidjson/stringbuffer.h | 115 +- .../rapidjson/include/rapidjson/writer.h | 889 +++-- Source/ThirdParty/rapidjson/license.txt | 57 + Source/Tools/AssetImporter/AssetImporter.cpp | 83 +- Source/Tools/PackageTool/PackageTool.cpp | 200 +- 718 files changed, 27779 insertions(+), 12339 deletions(-) create mode 100644 CMake/Modules/PostProcessForWebModule.cmake create mode 100644 Source/Atomic/Physics/RaycastVehicle.cpp create mode 100644 Source/Atomic/Physics/RaycastVehicle.h delete mode 100644 Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp delete mode 100644 Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp create mode 100644 Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h create mode 100644 Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp create mode 100644 Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h create mode 100644 Source/ThirdParty/Bullet/src/LinearMath/btThreads.cpp create mode 100644 Source/ThirdParty/Bullet/src/LinearMath/btThreads.h delete mode 100644 Source/ThirdParty/FreeType/docs/VERSION.DLL create mode 100644 Source/ThirdParty/FreeType/docs/freetype-config.1 create mode 100644 Source/ThirdParty/FreeType/include/freetype/ftpcfdrv.h delete mode 100644 Source/ThirdParty/FreeType/include/freetype/ftxf86.h delete mode 100644 Source/ThirdParty/FreeType/include/freetype/internal/services/svxf86nm.h delete mode 100644 Source/ThirdParty/FreeType/src/base/ftxf86.c create mode 100644 Source/ThirdParty/LZ4/LICENSE create mode 100644 Source/ThirdParty/LZ4/lz4opt.h delete mode 100644 Source/ThirdParty/rapidjson/include/rapidjson/filestream.h create mode 100644 Source/ThirdParty/rapidjson/license.txt diff --git a/.gitignore b/.gitignore index 67988a68a4..b125df44da 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ Script/TypeScript/**/*.d.ts !Script/TypeScript/**/*Work.d.ts Script/Haxe/* **/.vscode +.idea diff --git a/Build/CMake/Modules/AtomicMac.cmake b/Build/CMake/Modules/AtomicMac.cmake index 1aa22e0d22..50b071e423 100644 --- a/Build/CMake/Modules/AtomicMac.cmake +++ b/Build/CMake/Modules/AtomicMac.cmake @@ -20,4 +20,4 @@ else () endif () set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -stdlib=libc++") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -framework AudioToolbox -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreVideo -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -framework AudioToolbox -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreVideo -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security -framework SystemConfiguration") diff --git a/CMake/Modules/PostProcessForWebModule.cmake b/CMake/Modules/PostProcessForWebModule.cmake new file mode 100644 index 0000000000..7693127838 --- /dev/null +++ b/CMake/Modules/PostProcessForWebModule.cmake @@ -0,0 +1,35 @@ +# +# Copyright (c) 2008-2017 the Urho3D project. +# +# 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. +# + +# Post process to glue the main module and side module(s) together + +string (REPLACE " " .js',' SIDE_MODULES "'${SIDE_MODULES}.js'") # Stringify for string replacement +if (HAS_SHELL_FILE) + file (READ ${TARGET_FILE} CONTENT) + string (REPLACE ${TARGET_NAME}.js libUrho3D.js CONTENT "${CONTENT}") # Stringify to preserve semicolons + # Assume HTML shell-file has Module object without the 'dynamicLibraries' prop defined yet + string (REGEX REPLACE "(var Module *= *{)" \\1dynamicLibraries:[${SIDE_MODULES}], CONTENT "${CONTENT}") + file (WRITE ${TARGET_FILE} "${CONTENT}") +else () + file (READ ${TARGET_DIR}/libUrho3D.js CONTENT) + file (WRITE ${TARGET_DIR}/${TARGET_NAME}.main.js "var Module={dynamicLibraries:[${SIDE_MODULES}]};${CONTENT}") +endif () diff --git a/Resources/CoreData/Shaders/GLSL/BRDF.glsl b/Resources/CoreData/Shaders/GLSL/BRDF.glsl index b226a4f461..b30bd057b2 100644 --- a/Resources/CoreData/Shaders/GLSL/BRDF.glsl +++ b/Resources/CoreData/Shaders/GLSL/BRDF.glsl @@ -21,12 +21,23 @@ return specular + (vec3(1.0, 1.0, 1.0) - specular) * sphericalGaussian; } + vec3 SchlickFresnelCustom(vec3 specular, float LdotH) + { + float ior = 0.25; + float airIor = 1.000277; + float f0 = (ior - airIor) / (ior + airIor); + float max_ior = 2.5; + f0 = clamp(f0 * f0, 0.0, (max_ior - airIor) / (max_ior + airIor)); + return specular * (f0 + (1 - f0) * pow(2, (-5.55473 * LdotH - 6.98316) * LdotH)); + } + //Get Fresnel //specular = the rgb specular color value of the pixel //VdotH = the dot product of the camera view direction and the half vector - vec3 Fresnel(vec3 specular, float VdotH) + vec3 Fresnel(vec3 specular, float VdotH, float LdotH) { - return SchlickFresnel(specular, VdotH); + return SchlickFresnelCustom(specular, LdotH); + //return SchlickFresnel(specular, VdotH); } // Smith GGX corrected Visibility @@ -42,13 +53,19 @@ return 0.5 / (lambdaV + lambdaL); } + float NeumannVisibility(float NdotV, float NdotL) + { + return NdotL * NdotV / max(1e-7, max(NdotL, NdotV)); + } + // Get Visibility // NdotL = the dot product of the normal and direction to the light // NdotV = the dot product of the normal and the camera view direction // roughness = the roughness of the pixel float Visibility(float NdotL, float NdotV, float roughness) { - return SmithGGXSchlickVisibility(NdotL, NdotV, roughness); + return NeumannVisibility(NdotV, NdotL); + //return SmithGGXSchlickVisibility(NdotL, NdotV, roughness); } // Blinn Distribution @@ -96,9 +113,20 @@ // NdotV = the normal dot with the camera view direction // NdotL = the normal dot with the light direction // VdotH = the camera view direction dot with the half vector - vec3 LambertianDiffuse(vec3 diffuseColor, float NdotL) + vec3 LambertianDiffuse(vec3 diffuseColor) + { + return diffuseColor * (1.0 / M_PI) ; + } + + // Custom Lambertian Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + vec3 CustomLambertianDiffuse(vec3 diffuseColor, float NdotV, float roughness) { - return diffuseColor * NdotL; + return diffuseColor * (1.0 / M_PI) * pow(NdotV, 0.5 + 0.3 * roughness); } // Burley Diffuse @@ -127,8 +155,9 @@ // VdotH = the camera view direction dot with the half vector vec3 Diffuse(vec3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH) { - //return LambertianDiffuse(diffuseColor, NdotL); - return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH); + //return LambertianDiffuse(diffuseColor); + return CustomLambertianDiffuse(diffuseColor, NdotV, roughness); + //return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH); } #endif diff --git a/Resources/CoreData/Shaders/GLSL/Constants.glsl b/Resources/CoreData/Shaders/GLSL/Constants.glsl index 4e83774795..a2d6c67005 100644 --- a/Resources/CoreData/Shaders/GLSL/Constants.glsl +++ b/Resources/CoreData/Shaders/GLSL/Constants.glsl @@ -2,6 +2,6 @@ #define M_EPSILON 0.0001 #ifdef PBR -#define ROUGHNESS_FLOOR 0.003 +#define ROUGHNESS_FLOOR 0.004 #define METALNESS_FLOOR 0.03 #endif diff --git a/Resources/CoreData/Shaders/GLSL/IBL.glsl b/Resources/CoreData/Shaders/GLSL/IBL.glsl index d84a636f26..0d8291988a 100644 --- a/Resources/CoreData/Shaders/GLSL/IBL.glsl +++ b/Resources/CoreData/Shaders/GLSL/IBL.glsl @@ -229,17 +229,16 @@ /// normal: surface normal /// reflection: vector of reflection off of the surface /// roughness: surface roughness - vec3 GetSpecularDominantDir(vec3 normal, vec3 reflection, float roughness) - { - float smoothness = 1.0 - roughness; - float lerpFactor = smoothness * (sqrt(smoothness) + roughness); - return mix(normal, reflection, lerpFactor); - } + // vec3 GetSpecularDominantDir(vec3 normal, vec3 reflection, float roughness) + // { + // float smoothness = 1.0 - roughness; + // float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + // return mix(normal, reflection, lerpFactor); + // } float GetMipFromRoughness(float roughness) { - float Level = 3 - 1.15 * log2( roughness ); - return 9.0 - 1 - Level; + return (roughness * 12.0 - pow(roughness, 6.0) * 1.5); } @@ -273,6 +272,7 @@ /// ambientOcclusion: ambient occlusion vec3 ImageBasedLighting(vec3 reflectVec, vec3 tangent, vec3 bitangent, vec3 wsNormal, vec3 toCamera, vec3 diffColor, vec3 specColor, float roughness, inout vec3 reflectionCubeColor) { + roughness = max(roughness, 0.08); reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness); float ndv = clamp(dot(-toCamera, wsNormal), 0.0, 1.0); diff --git a/Resources/CoreData/Shaders/GLSL/PBR.glsl b/Resources/CoreData/Shaders/GLSL/PBR.glsl index 46de2c3482..d3433c8b8a 100644 --- a/Resources/CoreData/Shaders/GLSL/PBR.glsl +++ b/Resources/CoreData/Shaders/GLSL/PBR.glsl @@ -1,38 +1,70 @@ #include "BRDF.glsl" #ifdef COMPILEPS +#line 100 + vec3 GetSpecularDominantDir(vec3 normal, vec3 reflection, float roughness) + { + float smoothness = 1.0 - roughness; + float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + return mix(normal, reflection, lerpFactor); + } - vec3 SphereLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, out float ndl) + vec3 SphereLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, vec3 diffColor, out float ndl) { - vec3 pos = (cLightPosPS.xyz - worldPos); - float radius = cLightRad; + float specEnergy = 1.0f; - vec3 reflectVec = reflect(-toCamera, normal); - vec3 centreToRay = dot(pos, reflectVec) * reflectVec - pos; - vec3 closestPoint = pos + centreToRay * clamp(radius / length(centreToRay), 0.0, 1.0); + float radius = cLightRad / 100; + float rough2 = max(roughness, 0.08); + rough2 *= rough2; - vec3 l = normalize(closestPoint); - vec3 h = normalize(toCamera + l); + float radius2 = radius * radius; + float distToLightSqrd = dot(lightVec,lightVec); + float invDistToLight = inversesqrt(distToLightSqrd); + float sinAlphaSqr = clamp(radius2 / distToLightSqrd, 0.0, 1.0); + float sinAlpha = sqrt(sinAlphaSqr); - ndl = clamp(dot(normal, l), 0.0, 1.0); - float hdn = clamp(dot(h, normal), 0.0, 1.0); - float hdv = dot(h, toCamera); - float ndv = clamp(dot(normal, toCamera), 0.0, 1.0); + ndl = dot(normal, (lightVec * invDistToLight)); - float distL = length(pos); - float alpha = roughness * roughness; - float alphaPrime = clamp(radius / (distL * 2.0) + alpha, 0.0, 1.0); + if(ndl < sinAlpha) + { + ndl = max(ndl, -sinAlpha); + ndl = ((sinAlpha + ndl) * (sinAlpha + ndl)) / (4 * sinAlpha); + } + + float sphereAngle = clamp(radius * invDistToLight, 0.0, 1.0); + + specEnergy = rough2 / (rough2 + 0.5f * sphereAngle); + specEnergy *= specEnergy; - vec3 fresnelTerm = Fresnel(specColor, hdv) ; - float distTerm = Distribution(hdn, alphaPrime); - float visTerm = Visibility(ndl, ndv, roughness); + vec3 R = 2 * dot(toCamera, normal) * normal - toCamera; + R = GetSpecularDominantDir(normal, R, roughness); - return distTerm * visTerm * fresnelTerm ; + // Find closest point on sphere to ray + vec3 closestPointOnRay = dot(lightVec, R) * R; + vec3 centerToRay = closestPointOnRay - lightVec; + float invDistToRay = inversesqrt(dot(centerToRay, centerToRay)); + vec3 closestPointOnSphere = lightVec + centerToRay * clamp(radius * invDistToRay, 0.0, 1.0); + + lightVec = closestPointOnSphere; + vec3 L = normalize(lightVec); + + vec3 h = normalize(toCamera + L); + float hdn = clamp(dot(h, normal), 0.0, 1.0); + float hdv = dot(h, toCamera); + float ndv = clamp(dot(normal, toCamera),0.0, 1.0); + float hdl = clamp(dot(h, lightVec), 0.0, 1.0); + + vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, hdv) * ndl; + vec3 fresnelTerm = Fresnel(specColor, hdv, hdl) ; + float distTerm = Distribution(hdn, roughness); + float visTerm = Visibility(ndl, ndv, roughness); + vec3 specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI; + return diffuseFactor + specularFactor; } - vec3 TubeLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, out float ndl) + vec3 TubeLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, vec3 diffColor, out float ndl) { - float radius = cLightRad; - float len = cLightLength; + float radius = cLightRad / 100; + float len = cLightLength / 10; vec3 pos = (cLightPosPS.xyz - worldPos); vec3 reflectVec = reflect(-toCamera, normal); @@ -60,20 +92,22 @@ vec3 l = normalize(closestPoint); vec3 h = normalize(toCamera + l); - ndl = clamp(dot(normal, lightVec), 0.0, 1.0); + ndl = clamp(dot(normal, lightVec), 0.0, 1.0); float hdn = clamp(dot(h, normal), 0.0, 1.0); float hdv = dot(h, toCamera); - float ndv = clamp(dot(normal, toCamera), 0.0 ,1.0); + float ndv = clamp(dot(normal, toCamera), 0.0, 1.0); + float hdl = clamp(dot(h, lightVec), 0.0, 1.0); float distL = length(closestPoint); - float alpha = roughness * roughness; + float alpha = max(roughness, 0.08) * max(roughness, 0.08); float alphaPrime = clamp(radius / (distL * 2.0) + alpha, 0.0, 1.0); - vec3 fresnelTerm = Fresnel(specColor, hdv) ; - float distTerm = Distribution(hdn, alphaPrime); - float visTerm = Visibility(ndl, ndv, roughness); - - return distTerm * visTerm * fresnelTerm ; + vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, hdv) * ndl; + vec3 fresnelTerm = Fresnel(specColor, hdv, hdl) ; + float distTerm = Distribution(hdn, roughness); + float visTerm = Visibility(ndl, ndv, roughness); + vec3 specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI; + return diffuseFactor + specularFactor; } //Return the PBR BRDF value @@ -87,10 +121,11 @@ vec3 GetBRDF(vec3 worldPos, vec3 lightDir, vec3 lightVec, vec3 toCamera, vec3 normal, float roughness, vec3 diffColor, vec3 specColor) { vec3 Hn = normalize(toCamera + lightDir); - float vdh = clamp((dot(toCamera, Hn)), M_EPSILON, 1.0); - float ndh = clamp((dot(normal, Hn)), M_EPSILON, 1.0); - float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0); - float ndv = clamp((dot(normal, toCamera)), M_EPSILON, 1.0); + float vdh = clamp(dot(toCamera, Hn), M_EPSILON, 1.0); + float ndh = clamp(dot(normal, Hn), M_EPSILON, 1.0); + float ndl = clamp(dot(normal, lightVec), M_EPSILON, 1.0); + float ldh = clamp(dot(lightVec, Hn), M_EPSILON, 1.0); + float ndv = abs(dot(normal, toCamera)) + 1e-5; vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh); vec3 specularFactor = vec3(0.0, 0.0, 0.0); @@ -100,22 +135,23 @@ { if(cLightLength > 0.0) { - specularFactor = TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); + specularFactor = TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, diffColor, ndl); specularFactor *= ndl; } else { - specularFactor = SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); + specularFactor = SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, diffColor, ndl); specularFactor *= ndl; } } else { - vec3 fresnelTerm = Fresnel(specColor, vdh) ; + vec3 fresnelTerm = Fresnel(specColor, vdh, ldh) ; float distTerm = Distribution(ndh, roughness); float visTerm = Visibility(ndl, ndv, roughness); specularFactor = fresnelTerm * distTerm * visTerm / M_PI; + return diffuseFactor + specularFactor; } #endif diff --git a/Resources/CoreData/Shaders/HLSL/BRDF.hlsl b/Resources/CoreData/Shaders/HLSL/BRDF.hlsl index 98aa1f8a58..2b58db1568 100644 --- a/Resources/CoreData/Shaders/HLSL/BRDF.hlsl +++ b/Resources/CoreData/Shaders/HLSL/BRDF.hlsl @@ -21,12 +21,23 @@ return specular + (float3(1.0, 1.0, 1.0) - specular) * sphericalGaussian; } + float3 SchlickFresnelCustom(float3 specular, float LdotH) + { + float ior = 0.25; + float airIor = 1.000277; + float f0 = (ior - airIor) / (ior + airIor); + const float max_ior = 2.5; + f0 = clamp(f0 * f0, 0.0, (max_ior - airIor) / (max_ior + airIor)); + return specular * (f0 + (1 - f0) * pow(2, (-5.55473 * LdotH - 6.98316) * LdotH)); + } + //Get Fresnel //specular = the rgb specular color value of the pixel //VdotH = the dot product of the camera view direction and the half vector - float3 Fresnel(float3 specular, float VdotH) + float3 Fresnel(float3 specular, float VdotH, float LdotH) { - return SchlickFresnel(specular, VdotH); + return SchlickFresnelCustom(specular, LdotH); + //return SchlickFresnel(specular, VdotH); } // Smith GGX corrected Visibility @@ -42,13 +53,19 @@ return 0.5 / (lambdaV + lambdaL); } + float NeumannVisibility(float NdotV, float NdotL) + { + return NdotL * NdotV / max(1e-7, max(NdotL, NdotV)); + } + // Get Visibility // NdotL = the dot product of the normal and direction to the light // NdotV = the dot product of the normal and the camera view direction // roughness = the roughness of the pixel float Visibility(float NdotL, float NdotV, float roughness) { - return SmithGGXSchlickVisibility(NdotL, NdotV, roughness); + return NeumannVisibility(NdotV, NdotL); + //return SmithGGXSchlickVisibility(NdotL, NdotV, roughness); } // GGX Distribution @@ -96,9 +113,20 @@ // NdotV = the normal dot with the camera view direction // NdotL = the normal dot with the light direction // VdotH = the camera view direction dot with the half vector - float3 LambertianDiffuse(float3 diffuseColor, float NdotL) + float3 LambertianDiffuse(float3 diffuseColor) + { + return diffuseColor * (1.0 / M_PI) ; + } + + // Custom Lambertian Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + float3 CustomLambertianDiffuse(float3 diffuseColor, float NdotV, float roughness) { - return diffuseColor * NdotL; + return diffuseColor * (1.0 / M_PI) * pow(NdotV, 0.5 + 0.3 * roughness); } // Burley Diffuse @@ -127,8 +155,9 @@ // VdotH = the camera view direction dot with the half vector float3 Diffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH) { - //return LambertianDiffuse(diffuseColor, NdotL); - return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH); + //return LambertianDiffuse(diffuseColor); + return CustomLambertianDiffuse(diffuseColor, NdotV, roughness); + //return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH); } #endif diff --git a/Resources/CoreData/Shaders/HLSL/Constants.hlsl b/Resources/CoreData/Shaders/HLSL/Constants.hlsl index 4e83774795..a2d6c67005 100644 --- a/Resources/CoreData/Shaders/HLSL/Constants.hlsl +++ b/Resources/CoreData/Shaders/HLSL/Constants.hlsl @@ -2,6 +2,6 @@ #define M_EPSILON 0.0001 #ifdef PBR -#define ROUGHNESS_FLOOR 0.003 +#define ROUGHNESS_FLOOR 0.004 #define METALNESS_FLOOR 0.03 #endif diff --git a/Resources/CoreData/Shaders/HLSL/IBL.hlsl b/Resources/CoreData/Shaders/HLSL/IBL.hlsl index 585cf39f0f..997ff30913 100644 --- a/Resources/CoreData/Shaders/HLSL/IBL.hlsl +++ b/Resources/CoreData/Shaders/HLSL/IBL.hlsl @@ -220,17 +220,16 @@ /// normal: surface normal /// reflection: vector of reflection off of the surface /// roughness: surface roughness - float3 GetSpecularDominantDir(float3 normal, float3 reflection, float roughness) - { - const float smoothness = 1.0 - roughness; - const float lerpFactor = smoothness * (sqrt(smoothness) + roughness); - return lerp(normal, reflection, lerpFactor); - } + // float3 GetSpecularDominantDir(float3 normal, float3 reflection, float roughness) + // { + // const float smoothness = 1.0 - roughness; + // const float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + // return lerp(normal, reflection, lerpFactor); + // } float GetMipFromRoughness(float roughness) { - float Level = 3 - 1.15 * log2( roughness ); - return 9.0 - 1 - Level; + return (roughness * 12.0 - pow(roughness, 6.0) * 1.5); } @@ -264,6 +263,7 @@ /// ambientOcclusion: ambient occlusion float3 ImageBasedLighting(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor) { + roughness = max(roughness, 0.08); reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness); const float ndv = saturate(dot(-toCamera, wsNormal)); diff --git a/Resources/CoreData/Shaders/HLSL/PBR.hlsl b/Resources/CoreData/Shaders/HLSL/PBR.hlsl index 4f95434e91..da2b450c8f 100644 --- a/Resources/CoreData/Shaders/HLSL/PBR.hlsl +++ b/Resources/CoreData/Shaders/HLSL/PBR.hlsl @@ -1,40 +1,71 @@ #include "BRDF.hlsl" #ifdef COMPILEPS - + float3 GetSpecularDominantDir(float3 normal, float3 reflection, float roughness) + { + const float smoothness = 1.0 - roughness; + const float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + return lerp(normal, reflection, lerpFactor); + } - float3 SphereLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl) + float3 SphereLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, float3 diffColor, out float ndl) { - float3 pos = (cLightPosPS.xyz - worldPos); - float radius = cLightRad; + float specEnergy = 1.0f; - float3 reflectVec = reflect(-toCamera, normal); - float3 centreToRay = dot(pos, reflectVec) * reflectVec - pos; - float3 closestPoint = pos + centreToRay * saturate(radius / length(centreToRay)); + float radius = cLightRad / 100; + float rough2 = max(roughness, 0.08); + rough2 *= rough2; - float3 l = normalize(closestPoint); - float3 h = normalize(toCamera + l); + float radius2 = radius * radius; + float distToLightSqrd = dot(lightVec,lightVec); + float invDistToLight = rsqrt(distToLightSqrd); + float sinAlphaSqr = saturate(radius2 / distToLightSqrd); + float sinAlpha = sqrt(sinAlphaSqr); + + ndl = dot(normal, (lightVec * invDistToLight)); + + if(ndl < sinAlpha) + { + ndl = max(ndl, -sinAlpha); + ndl = ((sinAlpha + ndl) * (sinAlpha + ndl)) / (4 * sinAlpha); + } + + float sphereAngle = saturate(radius * invDistToLight); + + specEnergy = rough2 / (rough2 + 0.5f * sphereAngle); + specEnergy *= specEnergy; - ndl = saturate(dot(normal, l)); + float3 R = 2 * dot(toCamera, normal) * normal - toCamera; + R = GetSpecularDominantDir(normal, R, roughness); + + // Find closest point on sphere to ray + float3 closestPointOnRay = dot(lightVec, R) * R; + float3 centerToRay = closestPointOnRay - lightVec; + float invDistToRay = rsqrt(dot(centerToRay, centerToRay)); + float3 closestPointOnSphere = lightVec + centerToRay * saturate(radius * invDistToRay); + + lightVec = closestPointOnSphere; + float3 L = normalize(lightVec); + + float3 h = normalize(toCamera + L); float hdn = saturate(dot(h, normal)); float hdv = dot(h, toCamera); float ndv = saturate(dot(normal, toCamera)); + float hdl = saturate(dot(h, lightVec)); - float distL = length(pos); - float alpha = roughness * roughness; - float alphaPrime = saturate(radius / (distL * 2.0) + alpha); - - const float3 fresnelTerm = Fresnel(specColor, hdv) ; - const float distTerm = Distribution(hdn, alphaPrime); - const float visTerm = Visibility(ndl, ndv, roughness); + const float3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, hdv) * ndl; + const float3 fresnelTerm = Fresnel(specColor, hdv, hdl) ; + const float distTerm = Distribution(hdn, roughness); + const float visTerm = Visibility(ndl, ndv, roughness); + float3 specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI; + return diffuseFactor + specularFactor; - return distTerm * visTerm * fresnelTerm ; } - float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl) + float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, float3 diffColor, out float ndl) { - float radius = cLightRad; - float len = cLightLength; + float radius = cLightRad / 100; + float len = cLightLength / 10; float3 pos = (cLightPosPS.xyz - worldPos); float3 reflectVec = reflect(-toCamera, normal); @@ -66,16 +97,18 @@ float hdn = saturate(dot(h, normal)); float hdv = dot(h, toCamera); float ndv = saturate(dot(normal, toCamera)); + float hdl = saturate(dot(h, lightVec)); float distL = length(closestPoint); - float alpha = roughness * roughness; + float alpha = max(roughness, 0.08) * max(roughness, 0.08); float alphaPrime = saturate(radius / (distL * 2.0) + alpha); - const float3 fresnelTerm = Fresnel(specColor, hdv) ; - const float distTerm = Distribution(hdn, alphaPrime); - const float visTerm = Visibility(ndl, ndv, roughness); - - return distTerm * visTerm * fresnelTerm ; + const float3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, hdv) * ndl; + const float3 fresnelTerm = Fresnel(specColor, hdv, hdl) ; + const float distTerm = Distribution(hdn, roughness); + const float visTerm = Visibility(ndl, ndv, roughness); + float3 specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI; + return diffuseFactor + specularFactor; } //Return the PBR BRDF value @@ -94,6 +127,7 @@ const float ndh = clamp((dot(normal, Hn)), M_EPSILON, 1.0); float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0); const float ndv = clamp((dot(normal, toCamera)), M_EPSILON, 1.0); + const float ldh = clamp((dot(lightVec, Hn)), M_EPSILON, 1.0); const float3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh) * ndl; float3 specularFactor = 0; @@ -103,21 +137,21 @@ { if(cLightLength > 0.0) { - specularFactor = TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); - specularFactor *= ndl; + return TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, diffColor, ndl); + } else { - specularFactor = SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); - specularFactor *= ndl; + return SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, diffColor, ndl); } } else { - const float3 fresnelTerm = Fresnel(specColor, vdh) ; + const float3 fresnelTerm = Fresnel(specColor, vdh, ldh) ; const float distTerm = Distribution(ndh, roughness); const float visTerm = Visibility(ndl, ndv, roughness); specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI; + return diffuseFactor + specularFactor; } #endif diff --git a/Script/Packages/Atomic/Resource.json b/Script/Packages/Atomic/Resource.json index 8b93f0a324..8d0ccff558 100755 --- a/Script/Packages/Atomic/Resource.json +++ b/Script/Packages/Atomic/Resource.json @@ -2,7 +2,7 @@ "name" : "Resource", "sources" : ["Source/Atomic/Resource"], "includes" : [""], - "classes" : ["Resource", "ResourceCache", "XMLFile", "PListFile", "JSONFile", "Image", "ResourceNameIterator"], + "classes" : ["Resource", "ResourceWithMetadata", "ResourceCache", "XMLFile", "PListFile", "JSONFile", "Image", "ResourceNameIterator"], "overloads": { "Image": { "GetPixel": ["int", "int"], diff --git a/Source/Atomic/Atomic2D/CollisionChain2D.cpp b/Source/Atomic/Atomic2D/CollisionChain2D.cpp index 7d7bc62029..8a2d8f0c54 100644 --- a/Source/Atomic/Atomic2D/CollisionChain2D.cpp +++ b/Source/Atomic/Atomic2D/CollisionChain2D.cpp @@ -135,6 +135,7 @@ void CollisionChain2D::RecreateFixture() for (unsigned i = 0; i < count; ++i) b2Vertices[i] = ToB2Vec2(vertices_[i] * worldScale); + chainShape_.Clear(); if (loop_) chainShape_.CreateLoop(&b2Vertices[0], count); else diff --git a/Source/Atomic/Atomic2D/CollisionShape2D.cpp b/Source/Atomic/Atomic2D/CollisionShape2D.cpp index c97721c202..2fd58a4832 100644 --- a/Source/Atomic/Atomic2D/CollisionShape2D.cpp +++ b/Source/Atomic/Atomic2D/CollisionShape2D.cpp @@ -303,7 +303,8 @@ void CollisionShape2D::OnNodeSet(Node* node) void CollisionShape2D::OnMarkedDirty(Node* node) { - Vector3 newWorldScale = node_->GetWorldScale(); + // Use signed world scale to allow flipping of sprites by negative scale to work properly in regard to the collision shape + Vector3 newWorldScale = node_->GetSignedWorldScale(); Vector3 delta = newWorldScale - cachedWorldScale_; if (delta.DotProduct(delta) < 0.01f) diff --git a/Source/Atomic/Atomic2D/ParticleEmitter2D.cpp b/Source/Atomic/Atomic2D/ParticleEmitter2D.cpp index 494dc73c98..995a57df94 100644 --- a/Source/Atomic/Atomic2D/ParticleEmitter2D.cpp +++ b/Source/Atomic/Atomic2D/ParticleEmitter2D.cpp @@ -73,6 +73,7 @@ void ParticleEmitter2D::RegisterObject(Context* context) ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Sprite ", GetSpriteAttr, SetSpriteAttr, ResourceRef, ResourceRef(Sprite2D::GetTypeStatic()), AM_DEFAULT); ATOMIC_ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, BLEND_ALPHA, AM_DEFAULT); + ATOMIC_ACCESSOR_ATTRIBUTE("Is Emitting", IsEmitting, SetEmitting, bool, true, AM_DEFAULT); } void ParticleEmitter2D::OnSetEnabled() @@ -168,6 +169,15 @@ void ParticleEmitter2D::SetSpriteAttr(const ResourceRef& value) SetSprite(sprite); } +void ParticleEmitter2D::SetEmitting(bool enable) +{ + if (enable != emitting_) + { + emitting_ = enable; + emitParticleTime_ = 0.0f; + } +} + ResourceRef ParticleEmitter2D::GetSpriteAttr() const { return Sprite2D::SaveToResourceRef(sprite_); @@ -328,7 +338,7 @@ void ParticleEmitter2D::Update(float timeStep) } } - if (emissionTime_ > 0.0f) + if (emitting_ && emissionTime_ > 0.0f) { float worldAngle = GetNode()->GetWorldRotation().RollAngle(); @@ -464,17 +474,4 @@ void ParticleEmitter2D::UpdateParticle(Particle2D& particle, float timeStep, con boundingBoxMaxPoint_.z_ = Max(boundingBoxMaxPoint_.z_, particle.position_.z_); } -// ATOMIC BEGIN - -void ParticleEmitter2D::SetEmitting(bool enable) -{ - emitting_ = enable; -} -bool ParticleEmitter2D::IsEmitting() const -{ - return emitting_; -} - -// ATOMIC END - } diff --git a/Source/Atomic/Atomic2D/ParticleEmitter2D.h b/Source/Atomic/Atomic2D/ParticleEmitter2D.h index 93980a0fe5..4a6de9f9a4 100644 --- a/Source/Atomic/Atomic2D/ParticleEmitter2D.h +++ b/Source/Atomic/Atomic2D/ParticleEmitter2D.h @@ -96,6 +96,8 @@ class ATOMIC_API ParticleEmitter2D : public Drawable2D void SetBlendMode(BlendMode blendMode); /// Set max particles. void SetMaxParticles(unsigned maxParticles); + /// Set whether should be emitting. If the state was changed, also resets the emission period timer. + void SetEmitting(bool enable); /// Return particle effect. ParticleEffect2D* GetEffect() const; @@ -116,15 +118,8 @@ class ATOMIC_API ParticleEmitter2D : public Drawable2D void SetSpriteAttr(const ResourceRef& value); /// Return sprite attribute. ResourceRef GetSpriteAttr() const; - - // ATOMIC BEGIN - - /// Set emission state. - void SetEmitting(bool enable); - /// Return emission state. - bool IsEmitting() const; - - // ATOMIC END + /// Return whether is currently emitting. + bool IsEmitting() const { return emitting_; } private: /// Handle scene being assigned. @@ -158,20 +153,14 @@ class ATOMIC_API ParticleEmitter2D : public Drawable2D float emissionTime_; /// Emit particle time float emitParticleTime_; + /// Currently emitting flag. + bool emitting_; /// Particles. Vector particles_; /// Bounding box min point. Vector3 boundingBoxMinPoint_; /// Bounding box max point. Vector3 boundingBoxMaxPoint_; - - // ATOMIC BEGIN - - /// Emission enabled. - bool emitting_; - - // ATOMIC END - }; } diff --git a/Source/Atomic/Atomic2D/PhysicsEvents2D.h b/Source/Atomic/Atomic2D/PhysicsEvents2D.h index 40bb2651f3..afd91fa521 100644 --- a/Source/Atomic/Atomic2D/PhysicsEvents2D.h +++ b/Source/Atomic/Atomic2D/PhysicsEvents2D.h @@ -39,8 +39,7 @@ ATOMIC_EVENT(E_PHYSICSUPDATECONTACT2D, PhysicsUpdateContact2D) ATOMIC_PARAM(P_BODYB, BodyB); // RigidBody2D pointer ATOMIC_PARAM(P_NODEA, NodeA); // Node pointer ATOMIC_PARAM(P_NODEB, NodeB); // Node pointer - ATOMIC_PARAM(P_CONTACT, Contact); // b2Contact pointer - ATOMIC_PARAM(P_CONTACTPOINTS, ContactPoints); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. + ATOMIC_PARAM(P_CONTACTS, Contacts); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. ATOMIC_PARAM(P_SHAPEA, ShapeA); // CollisionShape2D pointer ATOMIC_PARAM(P_SHAPEB, ShapeB); // CollisionShape2D pointer ATOMIC_PARAM(P_ENABLED, Enabled); // bool [in/out] @@ -54,8 +53,7 @@ ATOMIC_EVENT(E_PHYSICSBEGINCONTACT2D, PhysicsBeginContact2D) ATOMIC_PARAM(P_BODYB, BodyB); // RigidBody2D pointer ATOMIC_PARAM(P_NODEA, NodeA); // Node pointer ATOMIC_PARAM(P_NODEB, NodeB); // Node pointer - ATOMIC_PARAM(P_CONTACT, Contact); // b2Contact pointer - ATOMIC_PARAM(P_CONTACTPOINTS, ContactPoints); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. + ATOMIC_PARAM(P_CONTACTS, Contacts); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. ATOMIC_PARAM(P_SHAPEA, ShapeA); // CollisionShape2D pointer ATOMIC_PARAM(P_SHAPEB, ShapeB); // CollisionShape2D pointer } @@ -68,8 +66,7 @@ ATOMIC_EVENT(E_PHYSICSENDCONTACT2D, PhysicsEndContact2D) ATOMIC_PARAM(P_BODYB, BodyB); // RigidBody2D pointer ATOMIC_PARAM(P_NODEA, NodeA); // Node pointer ATOMIC_PARAM(P_NODEB, NodeB); // Node pointer - ATOMIC_PARAM(P_CONTACT, Contact); // b2Contact pointer - ATOMIC_PARAM(P_CONTACTPOINTS, ContactPoints); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. + ATOMIC_PARAM(P_CONTACTS, Contacts); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. ATOMIC_PARAM(P_SHAPEA, ShapeA); // CollisionShape2D pointer ATOMIC_PARAM(P_SHAPEB, ShapeB); // CollisionShape2D pointer } @@ -80,8 +77,7 @@ ATOMIC_EVENT(E_NODEUPDATECONTACT2D, NodeUpdateContact2D) ATOMIC_PARAM(P_BODY, Body); // RigidBody2D pointer ATOMIC_PARAM(P_OTHERNODE, OtherNode); // Node pointer ATOMIC_PARAM(P_OTHERBODY, OtherBody); // RigidBody2D pointer - ATOMIC_PARAM(P_CONTACT, Contact); // b2Contact pointer - ATOMIC_PARAM(P_CONTACTPOINTS, ContactPoints); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. + ATOMIC_PARAM(P_CONTACTS, Contacts); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. ATOMIC_PARAM(P_SHAPE, Shape); // CollisionShape2D pointer ATOMIC_PARAM(P_OTHERSHAPE, OtherShape); // CollisionShape2D pointer ATOMIC_PARAM(P_ENABLED, Enabled); // bool [in/out] @@ -93,8 +89,7 @@ ATOMIC_EVENT(E_NODEBEGINCONTACT2D, NodeBeginContact2D) ATOMIC_PARAM(P_BODY, Body); // RigidBody2D pointer ATOMIC_PARAM(P_OTHERNODE, OtherNode); // Node pointer ATOMIC_PARAM(P_OTHERBODY, OtherBody); // RigidBody2D pointer - ATOMIC_PARAM(P_CONTACT, Contact); // b2Contact pointer - ATOMIC_PARAM(P_CONTACTPOINTS, ContactPoints); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. + ATOMIC_PARAM(P_CONTACTS, Contacts); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. ATOMIC_PARAM(P_SHAPE, Shape); // CollisionShape2D pointer ATOMIC_PARAM(P_OTHERSHAPE, OtherShape); // CollisionShape2D pointer } @@ -105,8 +100,7 @@ ATOMIC_EVENT(E_NODEENDCONTACT2D, NodeEndContact2D) ATOMIC_PARAM(P_BODY, Body); // RigidBody2D pointer ATOMIC_PARAM(P_OTHERNODE, OtherNode); // Node pointer ATOMIC_PARAM(P_OTHERBODY, OtherBody); // RigidBody2D pointer - ATOMIC_PARAM(P_CONTACT, Contact); // b2Contact pointer - ATOMIC_PARAM(P_CONTACTPOINTS, ContactPoints); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. + ATOMIC_PARAM(P_CONTACTS, Contacts); // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points. ATOMIC_PARAM(P_SHAPE, Shape); // CollisionShape2D pointer ATOMIC_PARAM(P_OTHERSHAPE, OtherShape); // CollisionShape2D pointer } diff --git a/Source/Atomic/Atomic2D/PhysicsWorld2D.cpp b/Source/Atomic/Atomic2D/PhysicsWorld2D.cpp index 94b56eea42..f1215b3811 100644 --- a/Source/Atomic/Atomic2D/PhysicsWorld2D.cpp +++ b/Source/Atomic/Atomic2D/PhysicsWorld2D.cpp @@ -48,30 +48,6 @@ static const Vector2 DEFAULT_GRAVITY(0.0f, -9.81f); static const int DEFAULT_VELOCITY_ITERATIONS = 8; static const int DEFAULT_POSITION_ITERATIONS = 3; -// Helper function to write contact info into buffer. -const PODVector& WriteContactInfo(VectorBuffer& buffer, b2Contact* contact) -{ - buffer.Clear(); - - // ATOMIC BEGIN - // Handle case when the body has been deleted during the event - if (!contact->GetFixtureA()->GetBody() || !contact->GetFixtureB()->GetBody() ) - { - return buffer.GetBuffer(); - } - // ATOMIC END - - b2WorldManifold worldManifold; - contact->GetWorldManifold(&worldManifold); - for (int i = 0; i < contact->GetManifold()->pointCount; ++i) - { - buffer.WriteVector2(Vector2(worldManifold.points[i].x, worldManifold.points[i].y)); - buffer.WriteVector2(Vector2(worldManifold.normal.x, worldManifold.normal.y)); - buffer.WriteFloat(worldManifold.separations[i]); - } - return buffer.GetBuffer(); -} - PhysicsWorld2D::PhysicsWorld2D(Context* context) : Component(context), gravity_(DEFAULT_GRAVITY), @@ -191,8 +167,7 @@ void PhysicsWorld2D::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) eventData[PhysicsUpdateContact2D::P_BODYB] = contactInfo.bodyB_.Get(); eventData[PhysicsUpdateContact2D::P_NODEA] = contactInfo.nodeA_.Get(); eventData[PhysicsUpdateContact2D::P_NODEB] = contactInfo.nodeB_.Get(); - eventData[PhysicsUpdateContact2D::P_CONTACT] = (void*)contactInfo.contact_; - eventData[PhysicsUpdateContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_); + eventData[PhysicsUpdateContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_); eventData[PhysicsUpdateContact2D::P_SHAPEA] = contactInfo.shapeA_.Get(); eventData[PhysicsUpdateContact2D::P_SHAPEB] = contactInfo.shapeB_.Get(); @@ -202,8 +177,7 @@ void PhysicsWorld2D::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) // Send node event eventData[NodeUpdateContact2D::P_ENABLED] = contact->IsEnabled(); - eventData[NodeUpdateContact2D::P_CONTACT] = (void*)contactInfo.contact_; - eventData[NodeUpdateContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_); + eventData[NodeUpdateContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_); if (contactInfo.nodeA_) { @@ -781,15 +755,13 @@ void PhysicsWorld2D::SendBeginContactEvents() eventData[P_BODYB] = contactInfo.bodyB_.Get(); eventData[P_NODEA] = contactInfo.nodeA_.Get(); eventData[P_NODEB] = contactInfo.nodeB_.Get(); - eventData[P_CONTACT] = (void*)contactInfo.contact_; - eventData[P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_); + eventData[P_CONTACTS] = contactInfo.Serialize(contacts_); eventData[P_SHAPEA] = contactInfo.shapeA_.Get(); eventData[P_SHAPEB] = contactInfo.shapeB_.Get(); SendEvent(E_PHYSICSBEGINCONTACT2D, eventData); - nodeEventData[NodeBeginContact2D::P_CONTACT] = (void*)contactInfo.contact_; - nodeEventData[NodeBeginContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_); + nodeEventData[NodeBeginContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_); if (contactInfo.nodeA_) { @@ -834,15 +806,13 @@ void PhysicsWorld2D::SendEndContactEvents() eventData[P_BODYB] = contactInfo.bodyB_.Get(); eventData[P_NODEA] = contactInfo.nodeA_.Get(); eventData[P_NODEB] = contactInfo.nodeB_.Get(); - eventData[P_CONTACT] = (void*)contactInfo.contact_; - eventData[P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_); + eventData[P_CONTACTS] = contactInfo.Serialize(contacts_); eventData[P_SHAPEA] = contactInfo.shapeA_.Get(); eventData[P_SHAPEB] = contactInfo.shapeB_.Get(); SendEvent(E_PHYSICSENDCONTACT2D, eventData); - nodeEventData[NodeEndContact2D::P_CONTACT] = (void*)contactInfo.contact_; - nodeEventData[NodeEndContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_); + nodeEventData[NodeEndContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_); if (contactInfo.nodeA_) { @@ -882,20 +852,31 @@ PhysicsWorld2D::ContactInfo::ContactInfo(b2Contact* contact) bodyB_ = (RigidBody2D*)(fixtureB->GetBody()->GetUserData()); nodeA_ = bodyA_->GetNode(); nodeB_ = bodyB_->GetNode(); - contact_ = contact; shapeA_ = (CollisionShape2D*)fixtureA->GetUserData(); shapeB_ = (CollisionShape2D*)fixtureB->GetUserData(); + + b2WorldManifold worldManifold; + contact->GetWorldManifold(&worldManifold); + numPoints_ = contact->GetManifold()->pointCount; + worldNormal_ = Vector2(worldManifold.normal.x, worldManifold.normal.y); + for (int i = 0; i < numPoints_; ++i) + { + worldPositions_[i] = Vector2(worldManifold.points[i].x, worldManifold.points[i].y); + separations_[i] = worldManifold.separations[i]; + } } -PhysicsWorld2D::ContactInfo::ContactInfo(const ContactInfo& other) : - bodyA_(other.bodyA_), - bodyB_(other.bodyB_), - nodeA_(other.nodeA_), - nodeB_(other.nodeB_), - contact_(other.contact_), - shapeA_(other.shapeA_), - shapeB_(other.shapeB_) +const PODVector& PhysicsWorld2D::ContactInfo::Serialize(VectorBuffer& buffer) const { + buffer.Clear(); + + for (int i = 0; i < numPoints_; ++i) + { + buffer.WriteVector2(worldPositions_[i]); + buffer.WriteVector2(worldNormal_); + buffer.WriteFloat(separations_[i]); + } + return buffer.GetBuffer(); } } diff --git a/Source/Atomic/Atomic2D/PhysicsWorld2D.h b/Source/Atomic/Atomic2D/PhysicsWorld2D.h index b3b9ff6480..789b98f35a 100644 --- a/Source/Atomic/Atomic2D/PhysicsWorld2D.h +++ b/Source/Atomic/Atomic2D/PhysicsWorld2D.h @@ -256,8 +256,8 @@ class ATOMIC_API PhysicsWorld2D : public Component, public b2ContactListener, pu ContactInfo(); /// Construct. ContactInfo(b2Contact* contract); - /// Copy construct. - ContactInfo(const ContactInfo& other); + /// Write contact info to buffer. + const PODVector& Serialize(VectorBuffer& buffer) const; /// Rigid body A. SharedPtr bodyA_; @@ -267,12 +267,18 @@ class ATOMIC_API PhysicsWorld2D : public Component, public b2ContactListener, pu SharedPtr nodeA_; /// Node B. SharedPtr nodeB_; - /// Box2D contact. - b2Contact* contact_; /// Shape A. SharedPtr shapeA_; /// Shape B. SharedPtr shapeB_; + /// Number of contact points. + int numPoints_; + /// Contact normal in world space. + Vector2 worldNormal_; + /// Contact positions in world space. + Vector2 worldPositions_[b2_maxManifoldPoints]; + /// Contact overlap values. + float separations_[b2_maxManifoldPoints]; }; /// Begin contact infos. Vector beginContactInfos_; diff --git a/Source/Atomic/Atomic2D/RigidBody2D.cpp b/Source/Atomic/Atomic2D/RigidBody2D.cpp index 3ecbf6ae87..aaa05bf4dd 100644 --- a/Source/Atomic/Atomic2D/RigidBody2D.cpp +++ b/Source/Atomic/Atomic2D/RigidBody2D.cpp @@ -111,7 +111,7 @@ void RigidBody2D::OnSetEnabled() void RigidBody2D::SetBodyType(BodyType2D type) { - b2BodyType bodyType = (b2BodyType)type; + b2BodyType bodyType = (b2BodyType)type; if (body_) { body_->SetType(bodyType); @@ -321,7 +321,7 @@ void RigidBody2D::SetLinearVelocity(const Vector2& linearVelocity) void RigidBody2D::SetAngularVelocity(float angularVelocity) { if (body_) - body_->SetAngularVelocity(angularVelocity); + body_->SetAngularVelocity(angularVelocity); else { if (bodyDef_.angularVelocity == angularVelocity) @@ -377,7 +377,7 @@ void RigidBody2D::CreateBody() if (!physicsWorld_ || !physicsWorld_->GetWorld()) return; - bodyDef_.position = ToB2Vec2(node_->GetWorldPosition());; + bodyDef_.position = ToB2Vec2(node_->GetWorldPosition()); bodyDef_.angle = node_->GetWorldRotation().RollAngle() * M_DEGTORAD; body_ = physicsWorld_->GetWorld()->CreateBody(&bodyDef_); @@ -607,16 +607,14 @@ void RigidBody2D::OnMarkedDirty(Node* node) // Check if transform has changed from the last one set in ApplyWorldTransform() b2Vec2 newPosition = ToB2Vec2(node_->GetWorldPosition()); float newAngle = node_->GetWorldRotation().RollAngle() * M_DEGTORAD; - if (newPosition != bodyDef_.position || newAngle != bodyDef_.angle) + + if (!body_) { - if (body_) - body_->SetTransform(newPosition, newAngle); - else - { - bodyDef_.position = newPosition; - bodyDef_.angle = newAngle; - } + bodyDef_.position = newPosition; + bodyDef_.angle = newAngle; } + else if (newPosition != body_->GetPosition() || newAngle != body_->GetAngle()) + body_->SetTransform(newPosition, newAngle); } } diff --git a/Source/Atomic/Atomic2D/SpriteSheet2D.cpp b/Source/Atomic/Atomic2D/SpriteSheet2D.cpp index 7e3fa2cbf1..09e99802b9 100644 --- a/Source/Atomic/Atomic2D/SpriteSheet2D.cpp +++ b/Source/Atomic/Atomic2D/SpriteSheet2D.cpp @@ -155,7 +155,7 @@ bool SpriteSheet2D::EndLoadFromPListFile() if (!texture_) { ATOMIC_LOGERROR("Could not load texture " + loadTextureName_); - loadXMLFile_.Reset(); + loadPListFile_.Reset(); loadTextureName_.Clear(); return false; } @@ -191,7 +191,7 @@ bool SpriteSheet2D::EndLoadFromPListFile() DefineSprite(name, rectangle, hotSpot, offset); } - loadXMLFile_.Reset(); + loadPListFile_.Reset(); loadTextureName_.Clear(); return true; } diff --git a/Source/Atomic/Atomic2D/TmxFile2D.cpp b/Source/Atomic/Atomic2D/TmxFile2D.cpp index e5dd53fbe6..4a80a8d8f5 100644 --- a/Source/Atomic/Atomic2D/TmxFile2D.cpp +++ b/Source/Atomic/Atomic2D/TmxFile2D.cpp @@ -666,6 +666,17 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element) propertySet->Load(tileElem.GetChild("properties")); gidToPropertySetMapping_[firstgid + tileElem.GetInt("id")] = propertySet; } + else if (tileElem.HasChild("objectgroup")) + { + XMLElement objectGroup = tileElem.GetChild("objectgroup"); + + if (objectGroup.HasChild("properties")) + { + SharedPtr propertySet(new PropertySet2D()); + propertySet->Load(objectGroup.GetChild("properties")); + gidToPropertySetMapping_[firstgid + tileElem.GetInt("id")] = propertySet; + } + } // ATOMIC BEGIN diff --git a/Source/Atomic/Audio/OggVorbisSoundStream.cpp b/Source/Atomic/Audio/OggVorbisSoundStream.cpp index 9d5893f836..8b57fdd011 100644 --- a/Source/Atomic/Audio/OggVorbisSoundStream.cpp +++ b/Source/Atomic/Audio/OggVorbisSoundStream.cpp @@ -59,6 +59,16 @@ OggVorbisSoundStream::~OggVorbisSoundStream() } } +bool OggVorbisSoundStream::Seek(unsigned sample_number) +{ + if (!decoder_) + return false; + + stb_vorbis* vorbis = static_cast(decoder_); + + return stb_vorbis_seek(vorbis, sample_number) == 1; +} + unsigned OggVorbisSoundStream::GetData(signed char* dest, unsigned numBytes) { if (!decoder_) diff --git a/Source/Atomic/Audio/OggVorbisSoundStream.h b/Source/Atomic/Audio/OggVorbisSoundStream.h index f16d334223..35e8b05ce9 100644 --- a/Source/Atomic/Audio/OggVorbisSoundStream.h +++ b/Source/Atomic/Audio/OggVorbisSoundStream.h @@ -39,6 +39,9 @@ class ATOMIC_API OggVorbisSoundStream : public SoundStream /// Destruct. ~OggVorbisSoundStream(); + /// Seek to sample number. Return true on success. + virtual bool Seek(unsigned sample_number); + /// Produce sound data into destination. Return number of bytes produced. Called by SoundSource from the mixing thread. virtual unsigned GetData(signed char* dest, unsigned numBytes); diff --git a/Source/Atomic/Audio/Sound.cpp b/Source/Atomic/Audio/Sound.cpp index 7c36a442a9..932aa2085f 100644 --- a/Source/Atomic/Audio/Sound.cpp +++ b/Source/Atomic/Audio/Sound.cpp @@ -59,7 +59,7 @@ struct WavHeader static const unsigned IP_SAFETY = 4; Sound::Sound(Context* context) : - Resource(context), + ResourceWithMetadata(context), repeat_(0), end_(0), dataSize_(0), @@ -348,9 +348,9 @@ void Sound::LoadParameters() return; XMLElement rootElem = file->GetRoot(); - XMLElement paramElem = rootElem.GetChild(); + LoadMetadataFromXML(rootElem); - while (paramElem) + for (XMLElement paramElem = rootElem.GetChild(); paramElem; paramElem = paramElem.GetNext()) { String name = paramElem.GetName(); @@ -373,8 +373,6 @@ void Sound::LoadParameters() if (paramElem.HasAttribute("start") && paramElem.HasAttribute("end")) SetLoop((unsigned)paramElem.GetInt("start"), (unsigned)paramElem.GetInt("end")); } - - paramElem = paramElem.GetNext(); } } diff --git a/Source/Atomic/Audio/Sound.h b/Source/Atomic/Audio/Sound.h index a6ffea554f..67ea2bc92d 100644 --- a/Source/Atomic/Audio/Sound.h +++ b/Source/Atomic/Audio/Sound.h @@ -31,9 +31,9 @@ namespace Atomic class SoundStream; /// %Sound resource. -class ATOMIC_API Sound : public Resource +class ATOMIC_API Sound : public ResourceWithMetadata { - ATOMIC_OBJECT(Sound, Resource); + ATOMIC_OBJECT(Sound, ResourceWithMetadata); public: /// Construct. diff --git a/Source/Atomic/Audio/SoundSource.cpp b/Source/Atomic/Audio/SoundSource.cpp index 3d85c8e237..1ba7b09ff9 100644 --- a/Source/Atomic/Audio/SoundSource.cpp +++ b/Source/Atomic/Audio/SoundSource.cpp @@ -144,6 +144,30 @@ void SoundSource::RegisterObject(Context* context) ATOMIC_ACCESSOR_ATTRIBUTE("Play Position", GetPositionAttr, SetPositionAttr, int, 0, AM_FILE); } +void SoundSource::Seek(float seekTime) +{ + // Ignore buffered sound stream + if (!audio_ || !sound_ || (soundStream_ && !sound_->IsCompressed())) + return; + + // Set to valid range + seekTime = Clamp(seekTime, 0.0f, sound_->GetLength()); + + if (!soundStream_) + { + // Raw or wav format + SetPositionAttr((int)(seekTime * (sound_->GetSampleSize() * sound_->GetFrequency()))); + } + else + { + // Ogg format + if (soundStream_->Seek((unsigned)(seekTime * soundStream_->GetFrequency()))) + { + timePosition_ = seekTime; + } + } +} + void SoundSource::Play(Sound* sound) { if (!audio_) diff --git a/Source/Atomic/Audio/SoundSource.h b/Source/Atomic/Audio/SoundSource.h index 4e3ff16c34..c406906a03 100644 --- a/Source/Atomic/Audio/SoundSource.h +++ b/Source/Atomic/Audio/SoundSource.h @@ -48,6 +48,8 @@ class ATOMIC_API SoundSource : public Component /// Register object factory. static void RegisterObject(Context* context); + /// Seek to time. + void Seek(float seekTime); /// Play a sound. void Play(Sound* sound); /// Play a sound with specified frequency. diff --git a/Source/Atomic/Audio/SoundStream.cpp b/Source/Atomic/Audio/SoundStream.cpp index cdab2a9f62..83790d77f8 100644 --- a/Source/Atomic/Audio/SoundStream.cpp +++ b/Source/Atomic/Audio/SoundStream.cpp @@ -39,6 +39,11 @@ SoundStream::~SoundStream() { } +bool SoundStream::Seek(unsigned int sample_number) +{ + return false; +} + void SoundStream::SetFormat(unsigned frequency, bool sixteenBit, bool stereo) { frequency_ = frequency; diff --git a/Source/Atomic/Audio/SoundStream.h b/Source/Atomic/Audio/SoundStream.h index 6c5ba6164f..9bace30aee 100644 --- a/Source/Atomic/Audio/SoundStream.h +++ b/Source/Atomic/Audio/SoundStream.h @@ -38,6 +38,9 @@ class ATOMIC_API SoundStream : public RefCounted /// Destruct. ~SoundStream(); + /// Seek to sample number. Return true on success. Need not be implemented by all streams. + virtual bool Seek(unsigned sample_number); + /// Produce sound data into destination. Return number of bytes produced. Called by SoundSource from the mixing thread. virtual unsigned GetData(signed char* dest, unsigned numBytes) = 0; diff --git a/Source/Atomic/Core/Context.cpp b/Source/Atomic/Core/Context.cpp index 1a39a8030a..99f3aaa1d9 100644 --- a/Source/Atomic/Core/Context.cpp +++ b/Source/Atomic/Core/Context.cpp @@ -317,8 +317,8 @@ void Context::ReleaseIK() if (ikInitCounter < 0) ATOMIC_LOGERROR("Too many calls to Context::ReleaseIK()"); } -#endif -#endif +#endif // ifdef URHO3D_IK +#endif // ifndef MINI_URHO void Context::CopyBaseAttributes(StringHash baseType, StringHash derivedType) { diff --git a/Source/Atomic/Core/Main.h b/Source/Atomic/Core/Main.h index 206812ef39..68b72a3a4c 100644 --- a/Source/Atomic/Core/Main.h +++ b/Source/Atomic/Core/Main.h @@ -67,8 +67,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, in Atomic::ParseArguments(GetCommandLineW()); \ return function; \ } -// Android or iOS: use SDL_main -#elif defined(__ANDROID__) || defined(IOS) +// Android or iOS or tvOS: use SDL_main +#elif defined(__ANDROID__) || defined(IOS) || defined(TVOS) #define ATOMIC_DEFINE_MAIN(function) \ extern "C" int SDL_main(int argc, char** argv); \ int SDL_main(int argc, char** argv) \ diff --git a/Source/Atomic/Core/ProcessUtils.cpp b/Source/Atomic/Core/ProcessUtils.cpp index a2b3fc3ab6..2a92b1c09e 100644 --- a/Source/Atomic/Core/ProcessUtils.cpp +++ b/Source/Atomic/Core/ProcessUtils.cpp @@ -23,6 +23,7 @@ #include "../Precompiled.h" #include "../Core/ProcessUtils.h" +#include "../Core/StringUtils.h" #include "../IO/FileSystem.h" #include @@ -33,21 +34,32 @@ #endif #if defined(IOS) -#include "../Math/MathDefs.h" #include +#elif defined(TVOS) +extern "C" unsigned SDL_TVOS_GetActiveProcessorCount(); #elif !defined(__linux__) && !defined(__EMSCRIPTEN__) -// ATOMIC BEGIN -#include -// ATOMIC END +#include #endif -#ifdef _WIN32 +#if defined(_WIN32) #include #include #if defined(_MSC_VER) #include +#include // For UNLEN. +#elif defined(__MINGW32__) +#include // For UNLEN. Apparently MSVC defines "" (with an upperscore 'L' but MinGW uses an underscore 'l'). +#include #endif -#else +#elif defined(__linux__) && !defined(__ANDROID__) +#include +#include +#include +#elif defined(__APPLE__) +#include +#include // For the detection functions inside GetLoginName(). +#endif +#ifndef _WIN32 #include #endif @@ -149,7 +161,7 @@ static void GetCPUData(struct CpuCoreCount* data) } } -#elif !defined(__EMSCRIPTEN__) +#elif !defined(__EMSCRIPTEN__) && !defined(TVOS) static void GetCPUData(struct cpu_id_t* data) { if (cpu_identify(0, data) < 0) @@ -206,7 +218,7 @@ void OpenConsoleWindow() void PrintUnicode(const String& str, bool error) { -#if !defined(__ANDROID__) && !defined(IOS) +#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS) #ifdef _WIN32 // If the output stream has been redirected, use fprintf instead of WriteConsoleW, // though it means that proper Unicode output will not work @@ -235,7 +247,7 @@ void PrintUnicodeLine(const String& str, bool error) void PrintLine(const String& str, bool error) { -#if !defined(__ANDROID__) && !defined(IOS) +#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS) fprintf(error ? stderr : stdout, "%s\n", str.CString()); #endif } @@ -373,7 +385,7 @@ String GetConsoleInput() } } } -#elif !defined(__ANDROID__) && !defined(IOS) +#elif !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS) int flags = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); for (;;) @@ -396,10 +408,12 @@ String GetPlatform() return "Android"; #elif defined(IOS) return "iOS"; +#elif defined(TVOS) + return "tvOS"; +#elif defined(__APPLE__) + return "macOS"; #elif defined(_WIN32) return "Windows"; -#elif defined(__APPLE__) - return "Mac OS X"; #elif defined(RPI) return "Raspberry Pi"; #elif defined(__EMSCRIPTEN__) @@ -416,12 +430,18 @@ unsigned GetNumPhysicalCPUs() #if defined(IOS) host_basic_info_data_t data; GetCPUData(&data); -#if defined(TARGET_IPHONE_SIMULATOR) +#if defined(TARGET_OS_SIMULATOR) // Hardcoded to dual-core on simulator mode even if the host has more return Min(2, data.physical_cpu); #else return data.physical_cpu; #endif +#elif defined(TVOS) +#if defined(TARGET_OS_SIMULATOR) + return Min(2, SDL_TVOS_GetActiveProcessorCount()); +#else + return SDL_TVOS_GetActiveProcessorCount(); +#endif #elif defined(__linux__) struct CpuCoreCount data; GetCPUData(&data); @@ -444,11 +464,17 @@ unsigned GetNumLogicalCPUs() #if defined(IOS) host_basic_info_data_t data; GetCPUData(&data); -#if defined(TARGET_IPHONE_SIMULATOR) +#if defined(TARGET_OS_SIMULATOR) return Min(2, data.logical_cpu); #else return data.logical_cpu; #endif +#elif defined(TVOS) +#if defined(TARGET_OS_SIMULATOR) + return Min(2, SDL_TVOS_GetActiveProcessorCount()); +#else + return SDL_TVOS_GetActiveProcessorCount(); +#endif #elif defined(__linux__) struct CpuCoreCount data; GetCPUData(&data); @@ -504,4 +530,196 @@ void QuoteArguments(Vector& args) // ATOMIC END +unsigned long long GetTotalMemory() +{ +#if defined(__linux__) && !defined(__ANDROID__) + struct sysinfo s; + if (sysinfo(&s) != -1) + return s.totalram; +#elif defined(_WIN32) + MEMORYSTATUSEX state; + state.dwLength = sizeof(state); + if (GlobalMemoryStatusEx(&state)) + return state.ullTotalPhys; +#elif defined(__APPLE__) + unsigned long long memSize; + size_t len = sizeof(memSize); + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + sysctl(mib, 2, &memSize, &len, NULL, 0); + return memSize; +#endif + return 0ull; +} + +String GetLoginName() +{ +#if defined(__linux__) && !defined(__ANDROID__) + struct passwd *p = getpwuid(getuid()); + if (p) + return p->pw_name; +#elif defined(_WIN32) + char name[UNLEN + 1]; + DWORD len = UNLEN + 1; + if (GetUserName(name, &len)) + return name; +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) + SCDynamicStoreRef s = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL); + if (s != NULL) + { + uid_t u; + CFStringRef n = SCDynamicStoreCopyConsoleUser(s, &u, NULL); + CFRelease(s); + if (n != NULL) + { + char name[256]; + Boolean b = CFStringGetCString(n, name, 256, kCFStringEncodingUTF8); + CFRelease(n); + + if (b == true) + return name; + } + } +#endif + return "(?)"; +} + +String GetHostName() +{ +#if (defined(__linux__) || defined(__APPLE__)) && !defined(__ANDROID__) + char buffer[256]; + if (gethostname(buffer, 256) == 0) + return buffer; +#elif defined(_WIN32) + char buffer[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD len = MAX_COMPUTERNAME_LENGTH + 1; + if (GetComputerName(buffer, &len)) + return buffer; +#endif + return String::EMPTY; +} + +// Disable Windows OS version functionality when compiling mini version for Web, see https://github.com/urho3d/Urho3D/issues/1998 +#if defined(_WIN32) && !defined(MINI_URHO) +typedef NTSTATUS (WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + +static void GetOS(RTL_OSVERSIONINFOW *r) +{ + HMODULE m = GetModuleHandle("ntdll.dll"); + if (m) + { + RtlGetVersionPtr fPtr = (RtlGetVersionPtr) GetProcAddress(m, "RtlGetVersion"); + if (r && fPtr && fPtr(r) == 0) + r->dwOSVersionInfoSize = sizeof *r; + } +} +#endif + +String GetOSVersion() +{ +#if defined(__linux__) && !defined(__ANDROID__) + struct utsname u; + if (uname(&u) == 0) + return String(u.sysname) + " " + u.release; +#elif defined(_WIN32) && !defined(MINI_URHO) + RTL_OSVERSIONINFOW r; + GetOS(&r); + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx + if (r.dwMajorVersion == 5 && r.dwMinorVersion == 0) + return "Windows 2000"; + else if (r.dwMajorVersion == 5 && r.dwMinorVersion == 1) + return "Windows XP"; + else if (r.dwMajorVersion == 5 && r.dwMinorVersion == 2) + return "Windows XP 64-Bit Edition/Windows Server 2003/Windows Server 2003 R2"; + else if (r.dwMajorVersion == 6 && r.dwMinorVersion == 0) + return "Windows Vista/Windows Server 2008"; + else if (r.dwMajorVersion == 6 && r.dwMinorVersion == 1) + return "Windows 7/Windows Server 2008 R2"; + else if (r.dwMajorVersion == 6 && r.dwMinorVersion == 2) + return "Windows 8/Windows Server 2012"; + else if (r.dwMajorVersion == 6 && r.dwMinorVersion == 3) + return "Windows 8.1/Windows Server 2012 R2"; + else if (r.dwMajorVersion == 10 && r.dwMinorVersion == 0) + return "Windows 10/Windows Server 2016"; + else + return "Windows Unidentified"; +#elif defined(__APPLE__) + char kernel_r[256]; + size_t size = sizeof(kernel_r); + + if (sysctlbyname("kern.osrelease", &kernel_r, &size, NULL, 0) != -1) + { + Vector kernel_version = String(kernel_r).Split('.'); + String version = "macOS/Mac OS X "; + int major = ToInt(kernel_version[0]); + int minor = ToInt(kernel_version[1]); + + // https://en.wikipedia.org/wiki/Darwin_(operating_system) + if (major == 16) // macOS Sierra + { + version += "Sierra "; + switch(minor) + { + case 0: version += "10.12.0 "; break; + case 1: version += "10.12.1 "; break; + case 3: version += "10.12.2 "; break; + } + } + else if (major == 15) // OS X El Capitan + { + version += "El Capitan "; + switch(minor) + { + case 0: version += "10.11.0 "; break; + case 6: version += "10.11.6 "; break; + } + } + else if (major == 14) // OS X Yosemite + { + version += "Yosemite "; + switch(minor) + { + case 0: version += "10.10.0 "; break; + case 5: version += "10.10.5 "; break; + } + } + else if (major == 13) // OS X Mavericks + { + version += "Mavericks "; + switch(minor) + { + case 0: version += "10.9.0 "; break; + case 4: version += "10.9.5 "; break; + } + } + else if (major == 12) // OS X Mountain Lion + { + version += "Mountain Lion "; + switch(minor) + { + case 0: version += "10.8.0 "; break; + case 6: version += "10.8.5 "; break; + } + } + else if (major == 11) // Mac OS X Lion + { + version += "Lion "; + switch(minor) + { + case 0: version += "10.7.0 "; break; + case 4: version += "10.7.5 "; break; + } + } + else + { + version += "Unknown "; + } + + return version + " (Darwin kernel " + kernel_version[0] + "." + kernel_version[1] + "." + kernel_version[2] + ")"; + } +#endif + return String::EMPTY; +} + } diff --git a/Source/Atomic/Core/ProcessUtils.h b/Source/Atomic/Core/ProcessUtils.h index ae7370a3f0..8321fd83e9 100644 --- a/Source/Atomic/Core/ProcessUtils.h +++ b/Source/Atomic/Core/ProcessUtils.h @@ -59,7 +59,7 @@ ATOMIC_API const Vector& ParseArguments(int argc, char** argv); ATOMIC_API const Vector& GetArguments(); /// Read input from the console window. Return empty if no input. ATOMIC_API String GetConsoleInput(); -/// Return the runtime platform identifier, one of "Windows", "Linux", "Mac OS X", "Android", "iOS", "Web" or "Raspberry Pi". +/// Return the runtime platform identifier. ATOMIC_API String GetPlatform(); /// Return the number of physical CPU cores. ATOMIC_API unsigned GetNumPhysicalCPUs(); @@ -69,6 +69,14 @@ ATOMIC_API unsigned GetNumLogicalCPUs(); ATOMIC_API void SetMiniDumpDir(const String& pathName); /// Return minidump write location. ATOMIC_API String GetMiniDumpDir(); +/// Return the total amount of useable memory. +ATOMIC_API unsigned long long GetTotalMemory(); +/// Return the name of the currently logged in user. +ATOMIC_API String GetLoginName(); +/// Return the name of the running machine. +ATOMIC_API String GetHostName(); +/// Return the version of the currently running OS. +ATOMIC_API String GetOSVersion(); // ATOMIC BEGIN @@ -76,5 +84,4 @@ ATOMIC_API String GetMiniDumpDir(); ATOMIC_API void QuoteArguments(Vector& args); // ATOMIC END - } diff --git a/Source/Atomic/Engine/Application.cpp b/Source/Atomic/Engine/Application.cpp index a4de5c03fa..ad30b1b75f 100644 --- a/Source/Atomic/Engine/Application.cpp +++ b/Source/Atomic/Engine/Application.cpp @@ -29,7 +29,7 @@ #include "../Core/Profiler.h" // ATOMIC END -#ifdef IOS +#if defined(IOS) || defined(TVOS) #include "../Graphics/Graphics.h" // ATOMIC BEGIN #include @@ -50,7 +50,7 @@ namespace Atomic bool Application::autoMetrics_ = false; // ATOMIC END -#if defined(IOS) || defined(__EMSCRIPTEN__) +#if defined(IOS) || defined(TVOS) || defined(__EMSCRIPTEN__) // Code for supporting SDL_iPhoneSetAnimationCallback() and emscripten_set_main_loop_arg() #if defined(__EMSCRIPTEN__) #include @@ -112,16 +112,16 @@ int Application::Run() if (exitCode_) return exitCode_; - // Platforms other than iOS and Emscripten run a blocking main loop -#if !defined(IOS) && !defined(__EMSCRIPTEN__) + // Platforms other than iOS/tvOS and Emscripten run a blocking main loop +#if !defined(IOS) && !defined(TVOS) && !defined(__EMSCRIPTEN__) while (!engine_->IsExiting()) engine_->RunFrame(); Stop(); - // iOS will setup a timer for running animation frames so eg. Game Center can run. In this case we do not + // iOS/tvOS will setup a timer for running animation frames so eg. Game Center can run. In this case we do not // support calling the Stop() function, as the application will never stop manually #else -#if defined(IOS) +#if defined(IOS) || defined(TVOS) SDL_iPhoneSetAnimationCallback(GetSubsystem()->GetWindow(), 1, &RunFrame, engine_); #elif defined(__EMSCRIPTEN__) emscripten_set_main_loop_arg(RunFrame, engine_, 0, 1); diff --git a/Source/Atomic/Engine/Application.h b/Source/Atomic/Engine/Application.h index edda2cef9a..7b6e8a013c 100644 --- a/Source/Atomic/Engine/Application.h +++ b/Source/Atomic/Engine/Application.h @@ -82,7 +82,7 @@ class ATOMIC_API Application : public Object }; // Macro for defining a main function which creates a Context and the application, then runs it -#ifndef IOS +#if !defined(IOS) && !defined(TVOS) #define ATOMIC_DEFINE_APPLICATION_MAIN(className) \ int RunApplication() \ { \ @@ -92,7 +92,7 @@ int RunApplication() \ } \ ATOMIC_DEFINE_MAIN(RunApplication()); #else -// On iOS we will let this function exit, so do not hold the context and application in SharedPtr's +// On iOS/tvOS we will let this function exit, so do not hold the context and application in SharedPtr's #define ATOMIC_DEFINE_APPLICATION_MAIN(className) \ int RunApplication() \ { \ diff --git a/Source/Atomic/Engine/Engine.cpp b/Source/Atomic/Engine/Engine.cpp index abd8e4cda4..df294e3653 100644 --- a/Source/Atomic/Engine/Engine.cpp +++ b/Source/Atomic/Engine/Engine.cpp @@ -66,6 +66,7 @@ #endif #ifdef ATOMIC_PHYSICS #include "../Physics/PhysicsWorld.h" +#include "../Physics/RaycastVehicle.h" #endif #include "../Resource/ResourceCache.h" #include "../Resource/Localization.h" @@ -113,7 +114,7 @@ Engine::Engine(Context* context) : timeStep_(0.0f), timeStepSmoothing_(2), minFps_(10), -#if defined(IOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__) +#if defined(IOS) || defined(TVOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__) maxFps_(60), maxInactiveFps_(10), pauseMinimized_(true), @@ -668,7 +669,7 @@ void Engine::SetPauseMinimized(bool enable) void Engine::SetAutoExit(bool enable) { // On mobile platforms exit is mandatory if requested by the platform itself and should not be attempted to be disabled -#if defined(__ANDROID__) || defined(IOS) +#if defined(__ANDROID__) || defined(IOS) || defined(TVOS) enable = true; #endif autoExit_ = enable; @@ -681,8 +682,8 @@ void Engine::SetNextTimeStep(float seconds) void Engine::Exit() { -#if defined(IOS) - // On iOS it's not legal for the application to exit on its own, instead it will be minimized with the home key +#if defined(IOS) || defined(TVOS) + // On iOS/tvOS it's not legal for the application to exit on its own, instead it will be minimized with the home key #else DoExit(); #endif @@ -806,10 +807,10 @@ void Engine::ApplyFrameLimit() #ifndef __EMSCRIPTEN__ // Perform waiting loop if maximum FPS set -#ifndef IOS +#if !defined(IOS) && !defined(TVOS) if (maxFps) #else - // If on iOS and target framerate is 60 or above, just let the animation callback handle frame timing + // If on iOS/tvOS and target framerate is 60 or above, just let the animation callback handle frame timing // instead of waiting ourselves if (maxFps < 60) #endif @@ -923,6 +924,8 @@ VariantMap Engine::ParseParameters(const Vector& arguments) ret[EP_FULL_SCREEN] = false; else if (argument == "borderless") ret[EP_BORDERLESS] = true; + else if (argument == "lowdpi") + ret[EP_HIGH_DPI] = false; else if (argument == "s") ret[EP_WINDOW_RESIZABLE] = true; else if (argument == "hd") diff --git a/Source/Atomic/Engine/Engine.h b/Source/Atomic/Engine/Engine.h index 36cc9baf31..2bf6345219 100644 --- a/Source/Atomic/Engine/Engine.h +++ b/Source/Atomic/Engine/Engine.h @@ -66,7 +66,7 @@ class ATOMIC_API Engine : public Object void SetAutoExit(bool enable); /// Override timestep of the next frame. Should be called in between RunFrame() calls. void SetNextTimeStep(float seconds); - /// Close the graphics window and set the exit flag. No-op on iOS, as an iOS application can not legally exit. + /// Close the graphics window and set the exit flag. No-op on iOS/tvOS, as an iOS/tvOS application can not legally exit. void Exit(); /// Dump information of all resources to the log. void DumpResources(bool dumpFileName = false); diff --git a/Source/Atomic/Graphics/AnimatedModel.cpp b/Source/Atomic/Graphics/AnimatedModel.cpp index 37f4817af4..1fe42f334d 100644 --- a/Source/Atomic/Graphics/AnimatedModel.cpp +++ b/Source/Atomic/Graphics/AnimatedModel.cpp @@ -611,11 +611,9 @@ void AnimatedModel::SetMorphWeight(unsigned index, float weight) return; // If morph vertex buffers have not been created yet, create now - if (weight > 0.0f && morphVertexBuffers_.Empty()) + if (weight != 0.0f && morphVertexBuffers_.Empty()) CloneGeometries(); - weight = Clamp(weight, 0.0f, 1.0f); - if (weight != morphs_[index].weight_) { morphs_[index].weight_ = weight; @@ -1463,7 +1461,7 @@ void AnimatedModel::UpdateMorphs() for (unsigned j = 0; j < morphs_.Size(); ++j) { - if (morphs_[j].weight_ > 0.0f) + if (morphs_[j].weight_ != 0.0f) { HashMap::Iterator k = morphs_[j].buffers_.Find(i); if (k != morphs_[j].buffers_.End()) diff --git a/Source/Atomic/Graphics/Animation.cpp b/Source/Atomic/Graphics/Animation.cpp index 3344a5095a..819f4e5326 100644 --- a/Source/Atomic/Graphics/Animation.cpp +++ b/Source/Atomic/Graphics/Animation.cpp @@ -107,7 +107,7 @@ void AnimationTrack::GetKeyFrameIndex(float time, unsigned& index) const } Animation::Animation(Context* context) : - Resource(context), + ResourceWithMetadata(context), length_(0.f) { } @@ -173,17 +173,16 @@ bool Animation::BeginLoad(Deserializer& source) if (file) { XMLElement rootElem = file->GetRoot(); - XMLElement triggerElem = rootElem.GetChild("trigger"); - while (triggerElem) + for (XMLElement triggerElem = rootElem.GetChild("trigger"); triggerElem; triggerElem = triggerElem.GetNext("trigger")) { if (triggerElem.HasAttribute("normalizedtime")) AddTrigger(triggerElem.GetFloat("normalizedtime"), true, triggerElem.GetVariant()); else if (triggerElem.HasAttribute("time")) AddTrigger(triggerElem.GetFloat("time"), false, triggerElem.GetVariant()); - - triggerElem = triggerElem.GetNext("trigger"); } + LoadMetadataFromXML(rootElem); + memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint); SetMemoryUse(memoryUse); return true; @@ -196,7 +195,7 @@ bool Animation::BeginLoad(Deserializer& source) if (jsonFile) { const JSONValue& rootVal = jsonFile->GetRoot(); - JSONArray triggerArray = rootVal.Get("triggers").GetArray(); + const JSONArray& triggerArray = rootVal.Get("triggers").GetArray(); for (unsigned i = 0; i < triggerArray.Size(); i++) { @@ -212,6 +211,9 @@ bool Animation::BeginLoad(Deserializer& source) } } + const JSONArray& metadataArray = rootVal.Get("metadata").GetArray(); + LoadMetadataFromJSON(metadataArray); + memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint); SetMemoryUse(memoryUse); return true; @@ -252,7 +254,7 @@ bool Animation::Save(Serializer& dest) const } // If triggers have been defined, write an XML file for them - if (triggers_.Size()) + if (!triggers_.Empty() || HasMetadata()) { File* destFile = dynamic_cast(&dest); if (destFile) @@ -269,6 +271,8 @@ bool Animation::Save(Serializer& dest) const triggerElem.SetVariant(triggers_[i].data_); } + SaveMetadataToXML(rootElem); + File xmlFile(context_, xmlName, FILE_WRITE); xml->Save(xmlFile); } @@ -373,29 +377,29 @@ SharedPtr Animation::Clone(const String& cloneName) const ret->length_ = length_; ret->tracks_ = tracks_; ret->triggers_ = triggers_; + ret->CopyMetadata(*this); ret->SetMemoryUse(GetMemoryUse()); - + return ret; -} +} -AnimationTrack* Animation::GetTrack(unsigned index) -{ - if (index >= GetNumTracks()) +AnimationTrack* Animation::GetTrack(unsigned index) +{ + if (index >= GetNumTracks()) return (AnimationTrack*) 0; - int j = 0; - for(HashMap::Iterator i = tracks_.Begin(); i != tracks_.End(); ++i) + int j = 0; + for(HashMap::Iterator i = tracks_.Begin(); i != tracks_.End(); ++i) { - if (j == index) - return &i->second_; - + if (j == index) + return &i->second_; + ++j; } - + return (AnimationTrack*) 0; } - AnimationTrack* Animation::GetTrack(const String& name) { HashMap::Iterator i = tracks_.Find(StringHash(name)); diff --git a/Source/Atomic/Graphics/Animation.h b/Source/Atomic/Graphics/Animation.h index 0a8d8c87e1..d6a335f333 100644 --- a/Source/Atomic/Graphics/Animation.h +++ b/Source/Atomic/Graphics/Animation.h @@ -107,9 +107,9 @@ static const unsigned char CHANNEL_ROTATION = 0x2; static const unsigned char CHANNEL_SCALE = 0x4; /// Skeletal animation resource. -class ATOMIC_API Animation : public Resource +class ATOMIC_API Animation : public ResourceWithMetadata { - ATOMIC_OBJECT(Animation, Resource); + ATOMIC_OBJECT(Animation, ResourceWithMetadata); public: /// Construct. @@ -162,9 +162,9 @@ class ATOMIC_API Animation : public Resource const HashMap& GetTracks() const { return tracks_; } /// Return number of animation tracks. - unsigned GetNumTracks() const { return tracks_.Size(); } + unsigned GetNumTracks() const { return tracks_.Size(); } - /// Return animation track by index. + /// Return animation track by index. AnimationTrack *GetTrack(unsigned index); /// Return animation track by name. diff --git a/Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp b/Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp index 7c6d83f4cf..bfa1737d1e 100644 --- a/Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp +++ b/Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp @@ -212,6 +212,8 @@ Graphics::Graphics(Context* context) : resizable_(false), highDPI_(false), vsync_(false), + monitor_(0), + refreshRate_(0), tripleBuffer_(false), flushGPU_(false), forceGL2_(false), @@ -382,6 +384,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, AdjustWindow(width, height, fullscreen, borderless, monitor); monitor_ = monitor; + refreshRate_ = refreshRate; if (maximize) { @@ -2110,13 +2113,15 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, } else { - if (newFullscreen || newBorderless) + SDL_Rect display_rect; + SDL_GetDisplayBounds(monitor, &display_rect); + + if (newFullscreen || (newBorderless && newWidth >= display_rect.w && newHeight >= display_rect.h)) { - // Reposition the window on the specified monitor - SDL_Rect display_rect; - SDL_GetDisplayBounds(monitor, &display_rect); + // Reposition the window on the specified monitor if it's supposed to cover the entire monitor SDL_SetWindowPosition(window_, display_rect.x, display_rect.y); } + SDL_SetWindowSize(window_, newWidth, newHeight); } diff --git a/Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp b/Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp index cc2cca8de1..e5c52d9bc2 100644 --- a/Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp +++ b/Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp @@ -2393,11 +2393,12 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, SDL_GetWindowSize(window_, &newWidth, &newHeight); } else { - if (newFullscreen || newBorderless) + SDL_Rect display_rect; + SDL_GetDisplayBounds(monitor, &display_rect); + + if (newFullscreen || (newBorderless && newWidth >= display_rect.w && newHeight >= display_rect.h)) { - // Reposition the window on the specified monitor - SDL_Rect display_rect; - SDL_GetDisplayBounds(monitor, &display_rect); + // Reposition the window on the specified monitor if it's supposed to cover the entire monitor SDL_SetWindowPosition(window_, display_rect.x, display_rect.y); } diff --git a/Source/Atomic/Graphics/Graphics.cpp b/Source/Atomic/Graphics/Graphics.cpp index b51f5d3883..2f7ca9672c 100644 --- a/Source/Atomic/Graphics/Graphics.cpp +++ b/Source/Atomic/Graphics/Graphics.cpp @@ -220,7 +220,7 @@ PODVector Graphics::GetResolutions(int monitor) const IntVector2 Graphics::GetDesktopResolution(int monitor) const { -#if !defined(__ANDROID__) && !defined(IOS) +#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS) SDL_DisplayMode mode; SDL_GetDesktopDisplayMode(monitor, &mode); return IntVector2(mode.w, mode.h); diff --git a/Source/Atomic/Graphics/GraphicsDefs.h b/Source/Atomic/Graphics/GraphicsDefs.h index 930ef68625..d5887b7a2a 100644 --- a/Source/Atomic/Graphics/GraphicsDefs.h +++ b/Source/Atomic/Graphics/GraphicsDefs.h @@ -31,7 +31,7 @@ namespace Atomic class Vector3; /// Graphics capability support level. Web platform (Emscripten) also uses OpenGL ES, but is considered a desktop platform capability-wise -#if defined(IOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__) +#if defined(IOS) || defined(TVOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__) #define MOBILE_GRAPHICS #else #define DESKTOP_GRAPHICS diff --git a/Source/Atomic/Graphics/Model.cpp b/Source/Atomic/Graphics/Model.cpp index 911fa5f3e6..0effa86de3 100644 --- a/Source/Atomic/Graphics/Model.cpp +++ b/Source/Atomic/Graphics/Model.cpp @@ -31,6 +31,9 @@ #include "../Graphics/VertexBuffer.h" #include "../IO/Log.h" #include "../IO/File.h" +#include "../IO/FileSystem.h" +#include "../Resource/ResourceCache.h" +#include "../Resource/XMLFile.h" #include "../DebugNew.h" @@ -58,7 +61,7 @@ unsigned LookupIndexBuffer(IndexBuffer* buffer, const Vector(); + String xmlName = ReplaceExtension(GetName(), ".xml"); + SharedPtr file(cache->GetTempResource(xmlName, false)); + if (file) + LoadMetadataFromXML(file->GetRoot()); -// ATOMIC END + SetMemoryUse(memoryUse); return true; } @@ -497,6 +503,25 @@ bool Model::Save(Serializer& dest) const // ATOMIC END + // Write metadata + if (HasMetadata()) + { + File* destFile = dynamic_cast(&dest); + if (destFile) + { + String xmlName = ReplaceExtension(destFile->GetName(), ".xml"); + + SharedPtr xml(new XMLFile(context_)); + XMLElement rootElem = xml->CreateRoot("model"); + SaveMetadataToXML(rootElem); + + File xmlFile(context_, xmlName, FILE_WRITE); + xml->Save(xmlFile); + } + else + ATOMIC_LOGWARNING("Can not save model metadata when not saving into a file"); + } + return true; } diff --git a/Source/Atomic/Graphics/Model.h b/Source/Atomic/Graphics/Model.h index ed3177907a..141ed531f4 100644 --- a/Source/Atomic/Graphics/Model.h +++ b/Source/Atomic/Graphics/Model.h @@ -111,9 +111,9 @@ static const unsigned MODEL_VERSION = 1; // ATOMIC END /// 3D model resource. -class ATOMIC_API Model : public Resource +class ATOMIC_API Model : public ResourceWithMetadata { - ATOMIC_OBJECT(Model, Resource); + ATOMIC_OBJECT(Model, ResourceWithMetadata); public: /// Construct. diff --git a/Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp b/Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp index ff5bd7f7f5..a27f34548f 100644 --- a/Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp +++ b/Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp @@ -236,6 +236,8 @@ Graphics::Graphics(Context* context_) : resizable_(false), highDPI_(false), vsync_(false), + monitor_(0), + refreshRate_(0), tripleBuffer_(false), sRGB_(false), forceGL2_(false), @@ -429,9 +431,10 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, SDL_Rect display_rect; SDL_GetDisplayBounds(monitor, &display_rect); SDL_SetWindowPosition(window_, display_rect.x, display_rect.y); + bool reposition = fullscreen || (borderless && width >= display_rect.w && height >= display_rect.h); - int x = fullscreen || borderless ? display_rect.x : position_.x_; - int y = fullscreen || borderless ? display_rect.y : position_.y_; + int x = reposition ? display_rect.x : position_.x_; + int y = reposition ? display_rect.y : position_.y_; unsigned flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; if (fullscreen) @@ -496,8 +499,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, // Set vsync SDL_GL_SetSwapInterval(vsync ? 1 : 0); - // Store the system FBO on IOS now -#ifdef IOS + // Store the system FBO on iOS/tvOS now +#if defined(IOS) || defined(TVOS) glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_); #endif @@ -508,6 +511,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, vsync_ = vsync; tripleBuffer_ = tripleBuffer; multiSample_ = multiSample; + monitor_ = monitor; + refreshRate_ = refreshRate; SDL_GL_GetDrawableSize(window_, &width_, &height_); if (!fullscreen) @@ -2087,8 +2092,8 @@ bool Graphics::GetDither() const bool Graphics::IsDeviceLost() const { - // On iOS treat window minimization as device loss, as it is forbidden to access OpenGL when minimized -#ifdef IOS + // On iOS and tvOS treat window minimization as device loss, as it is forbidden to access OpenGL when minimized +#if defined(IOS) || defined(TVOS) if (window_ && (SDL_GetWindowFlags(window_) & SDL_WINDOW_MINIMIZED) != 0) return true; #endif @@ -2418,7 +2423,7 @@ void Graphics::Release(bool clearGPUObjects, bool closeWindow) impl_->depthTextures_.Clear(); // End fullscreen mode first to counteract transition and getting stuck problems on OS X -#if defined(__APPLE__) && !defined(IOS) +#if defined(__APPLE__) && !defined(IOS) && !defined(TVOS) if (closeWindow && fullscreen_ && !externalWindow_) SDL_SetWindowFullscreen(window_, 0); #endif @@ -2511,7 +2516,7 @@ void Graphics::Restore() } #endif -#ifdef IOS +#if defined(IOS) || defined(TVOS) glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_); #endif @@ -2830,8 +2835,8 @@ void Graphics::CheckFeatureSupport() if (numSupportedRTs >= 4) deferredSupport_ = true; -#if defined(__APPLE__) && !defined(IOS) - // On OS X check for an Intel driver and use shadow map RGBA dummy color textures, because mixing +#if defined(__APPLE__) && !defined(IOS) && !defined(TVOS) + // On macOS check for an Intel driver and use shadow map RGBA dummy color textures, because mixing // depth-only FBO rendering and backbuffer rendering will bug, resulting in a black screen in full // screen mode, and incomplete shadow maps in windowed mode String renderer((const char*)glGetString(GL_RENDERER)); @@ -2870,9 +2875,8 @@ void Graphics::CheckFeatureSupport() } else { - #ifdef IOS - // iOS hack: depth renderbuffer seems to fail, so use depth textures for everything - // if supported +#if defined(IOS) || defined(TVOS) + // iOS hack: depth renderbuffer seems to fail, so use depth textures for everything if supported glesDepthStencilFormat = GL_DEPTH_COMPONENT; #endif shadowMapFormat_ = GL_DEPTH_COMPONENT; diff --git a/Source/Atomic/Graphics/OpenGL/OGLGraphicsImpl.h b/Source/Atomic/Graphics/OpenGL/OGLGraphicsImpl.h index 9275f158ff..f758f92714 100644 --- a/Source/Atomic/Graphics/OpenGL/OGLGraphicsImpl.h +++ b/Source/Atomic/Graphics/OpenGL/OGLGraphicsImpl.h @@ -29,7 +29,7 @@ #include "../../Graphics/Texture2D.h" #include "../../Math/Color.h" -#if defined(IOS) +#if defined(IOS) || defined(TVOS) #include #include #elif defined(__ANDROID__) || defined (__arm__) || defined(__aarch64__) || defined (__EMSCRIPTEN__) @@ -114,7 +114,7 @@ class ATOMIC_API GraphicsImpl private: /// SDL OpenGL context. SDL_GLContext context_; - /// IOS system framebuffer handle. + /// iOS/tvOS system framebuffer handle. unsigned systemFBO_; /// Active texture unit. unsigned activeTexture_; diff --git a/Source/Atomic/Graphics/OpenGL/OGLTexture2D.cpp b/Source/Atomic/Graphics/OpenGL/OGLTexture2D.cpp index 0d82ec86dd..c0bb9221e8 100644 --- a/Source/Atomic/Graphics/OpenGL/OGLTexture2D.cpp +++ b/Source/Atomic/Graphics/OpenGL/OGLTexture2D.cpp @@ -460,8 +460,8 @@ bool Texture2D::Create() requestedLevels_ = 1; else if (usage_ == TEXTURE_RENDERTARGET) { -#if defined(__EMSCRIPTEN__) || defined(IOS) - // glGenerateMipmap appears to not be working on WebGL or iOS, disable rendertarget mipmaps for now +#if defined(__EMSCRIPTEN__) || defined(IOS) || defined(TVOS) + // glGenerateMipmap appears to not be working on WebGL or iOS/tvOS, disable rendertarget mipmaps for now requestedLevels_ = 1; #else if (requestedLevels_ != 1) diff --git a/Source/Atomic/Graphics/OpenGL/OGLTextureCube.cpp b/Source/Atomic/Graphics/OpenGL/OGLTextureCube.cpp index 3d1f06f2e0..a7c8e1f6ff 100644 --- a/Source/Atomic/Graphics/OpenGL/OGLTextureCube.cpp +++ b/Source/Atomic/Graphics/OpenGL/OGLTextureCube.cpp @@ -485,8 +485,8 @@ bool TextureCube::Create() requestedLevels_ = 1; else if (usage_ == TEXTURE_RENDERTARGET) { -#if defined(__EMSCRIPTEN__) || defined(IOS) - // glGenerateMipmap appears to not be working on WebGL or iOS, disable rendertarget mipmaps for now +#if defined(__EMSCRIPTEN__) || defined(IOS) || defined(TVOS) + // glGenerateMipmap appears to not be working on WebGL or iOS/tvOS, disable rendertarget mipmaps for now requestedLevels_ = 1; #else if (requestedLevels_ != 1) diff --git a/Source/Atomic/Graphics/Text3D/Text3D.cpp b/Source/Atomic/Graphics/Text3D/Text3D.cpp index 795a5ada7c..9eb3278cbe 100644 --- a/Source/Atomic/Graphics/Text3D/Text3D.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3D.cpp @@ -78,7 +78,7 @@ void Text3D::RegisterObject(Context* context) ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Font", GetFontAttr, SetFontAttr, ResourceRef, ResourceRef(Text3DFont::GetTypeStatic()), AM_DEFAULT); ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT); - ATOMIC_ATTRIBUTE("Font Size", int, text_.fontSize_, TEXT3D_DEFAULT_FONT_SIZE, AM_DEFAULT); + ATOMIC_ATTRIBUTE("Font Size", float, text_.fontSize_, TEXT3D_DEFAULT_FONT_SIZE, AM_DEFAULT); ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Text", GetTextAttr, SetTextAttr, String, String::EMPTY, AM_DEFAULT); ATOMIC_ENUM_ATTRIBUTE("Text Alignment", text_.textAlignment_, horizontalAlignments, HA_LEFT, AM_DEFAULT); ATOMIC_ATTRIBUTE("Row Spacing", float, text_.rowSpacing_, 1.0f, AM_DEFAULT); @@ -185,7 +185,7 @@ void Text3D::SetMaterial(Material* material) UpdateTextMaterials(true); } -bool Text3D::SetFont(const String& fontName, int size) +bool Text3D::SetFont(const String& fontName, float size) { bool success = text_.SetFont(fontName, size); @@ -198,7 +198,7 @@ bool Text3D::SetFont(const String& fontName, int size) return success; } -bool Text3D::SetFont(Text3DFont* font, int size) +bool Text3D::SetFont(Text3DFont* font, float size) { bool success = text_.SetFont(font, size); @@ -209,7 +209,7 @@ bool Text3D::SetFont(Text3DFont* font, int size) return success; } -bool Text3D::SetFontSize(int size) +bool Text3D::SetFontSize(float size) { bool success = text_.SetFontSize(size); @@ -369,7 +369,7 @@ Text3DFont* Text3D::GetFont() const return text_.GetFont(); } -int Text3D::GetFontSize() const +float Text3D::GetFontSize() const { return text_.GetFontSize(); } @@ -454,12 +454,12 @@ int Text3D::GetRowWidth(unsigned index) const return text_.GetRowWidth(index); } -IntVector2 Text3D::GetCharPosition(unsigned index) +Vector2 Text3D::GetCharPosition(unsigned index) { return text_.GetCharPosition(index); } -IntVector2 Text3D::GetCharSize(unsigned index) +Vector2 Text3D::GetCharSize(unsigned index) { return text_.GetCharSize(index); } diff --git a/Source/Atomic/Graphics/Text3D/Text3D.h b/Source/Atomic/Graphics/Text3D/Text3D.h index b81daaead0..efd2bf8af1 100644 --- a/Source/Atomic/Graphics/Text3D/Text3D.h +++ b/Source/Atomic/Graphics/Text3D/Text3D.h @@ -55,11 +55,11 @@ class ATOMIC_API Text3D : public Drawable virtual UpdateGeometryType GetUpdateGeometryType(); /// Set font by looking from resource cache by name and font size. Return true if successful. - bool SetFont(const String& fontName, int size = TEXT3D_DEFAULT_FONT_SIZE); + bool SetFont(const String& fontName, float size = TEXT3D_DEFAULT_FONT_SIZE); /// Set font and font size. Return true if successful. - bool SetFont(Text3DFont* font, int size = TEXT3D_DEFAULT_FONT_SIZE); + bool SetFont(Text3DFont* font, float size = TEXT3D_DEFAULT_FONT_SIZE); /// Set font size only while retaining the existing font. Return true if successful. - bool SetFontSize(int size); + bool SetFontSize(float size); /// Set material. void SetMaterial(Material* material); /// Set text. Text is assumed to be either ASCII or UTF8-encoded. @@ -104,7 +104,7 @@ class ATOMIC_API Text3D : public Drawable /// Return font. Text3DFont* GetFont() const; /// Return font size. - int GetFontSize() const; + float GetFontSize() const; /// Return material. Material* GetMaterial() const; /// Return text. @@ -144,9 +144,9 @@ class ATOMIC_API Text3D : public Drawable /// Return width of row by index. int GetRowWidth(unsigned index) const; /// Return position of character by index relative to the text element origin. - IntVector2 GetCharPosition(unsigned index); + Vector2 GetCharPosition(unsigned index); /// Return size of character by index. - IntVector2 GetCharSize(unsigned index); + Vector2 GetCharSize(unsigned index); /// Return corner color. const Color& GetColor(Text3DCorner corner) const; /// Return opacity. diff --git a/Source/Atomic/Graphics/Text3D/Text3DBatch.cpp b/Source/Atomic/Graphics/Text3D/Text3DBatch.cpp index 5741d925d3..81cef8706a 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DBatch.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3DBatch.cpp @@ -79,32 +79,7 @@ void Text3DBatch::SetDefaultColor() } } - -unsigned Text3DBatch::GetInterpolatedColor(int x, int y) -{ - const IntVector2& size = element_->GetSize(); - - if (size.x_ && size.y_) - { - float cLerpX = Clamp((float)x / (float)size.x_, 0.0f, 1.0f); - float cLerpY = Clamp((float)y / (float)size.y_, 0.0f, 1.0f); - - Color topColor = element_->GetColor(C_TOPLEFT).Lerp(element_->GetColor(C_TOPRIGHT), cLerpX); - Color bottomColor = element_->GetColor(C_BOTTOMLEFT).Lerp(element_->GetColor(C_BOTTOMRIGHT), cLerpX); - Color color = topColor.Lerp(bottomColor, cLerpY); - color.a_ *= element_->GetOpacity(); - return color.ToUInt(); - } - else - { - Color color = element_->GetColor(C_TOPLEFT); - color.a_ *= element_->GetOpacity(); - return color.ToUInt(); - } -} - - -void Text3DBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight) +void Text3DBatch::AddQuad(float x, float y, float width, float height, int texOffsetX, int texOffsetY, int texWidth, int texHeight) { unsigned topLeftColor, topRightColor, bottomLeftColor, bottomRightColor; @@ -129,10 +104,10 @@ void Text3DBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, i const IntVector2& screenPos = IntVector2::ZERO; //element_->GetScreenPosition(); - float left = (float)(x + screenPos.x_) - posAdjust.x_; - float right = left + (float)width; - float top = (float)(y + screenPos.y_) - posAdjust.x_; - float bottom = top + (float)height; + float left = x + screenPos.x_ - posAdjust.x_; + float right = left + width; + float top = y + screenPos.y_ - posAdjust.x_; + float bottom = top + height; float leftUV = texOffsetX * invTextureSize_.x_; float topUV = texOffsetY * invTextureSize_.y_; @@ -444,6 +419,29 @@ bool Text3DBatch::Merge(const Text3DBatch& batch) return true; } +unsigned Text3DBatch::GetInterpolatedColor(float x, float y) +{ + const IntVector2& size = element_->GetSize(); + + if (size.x_ && size.y_) + { + float cLerpX = Clamp(x / (float)size.x_, 0.0f, 1.0f); + float cLerpY = Clamp(y / (float)size.y_, 0.0f, 1.0f); + + Color topColor = element_->GetColor(C_TOPLEFT).Lerp(element_->GetColor(C_TOPRIGHT), cLerpX); + Color bottomColor = element_->GetColor(C_BOTTOMLEFT).Lerp(element_->GetColor(C_BOTTOMRIGHT), cLerpX); + Color color = topColor.Lerp(bottomColor, cLerpY); + color.a_ *= element_->GetOpacity(); + return color.ToUInt(); + } + else + { + Color color = element_->GetColor(C_TOPLEFT); + color.a_ *= element_->GetOpacity(); + return color.ToUInt(); + } +} + void Text3DBatch::AddOrMerge(const Text3DBatch& batch, PODVector& batches) { if (batch.vertexEnd_ == batch.vertexStart_) diff --git a/Source/Atomic/Graphics/Text3D/Text3DBatch.h b/Source/Atomic/Graphics/Text3D/Text3DBatch.h index 50bce1d677..5e27447b3c 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DBatch.h +++ b/Source/Atomic/Graphics/Text3D/Text3DBatch.h @@ -51,7 +51,7 @@ class ATOMIC_API Text3DBatch /// Restore UI element's default color. void SetDefaultColor(); /// Add a quad. - void AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth = 0, int texHeight = 0); + void AddQuad(float x, float y, float width, float height, int texOffsetX, int texOffsetY, int texWidth = 0, int texHeight = 0); /// Add a quad using a transform matrix. void AddQuad(const Matrix3x4& transform, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth = 0, int texHeight = 0); @@ -67,7 +67,7 @@ class ATOMIC_API Text3DBatch /// Merge with another batch. bool Merge(const Text3DBatch& batch); /// Return an interpolated color for the element. - unsigned GetInterpolatedColor(int x, int y); + unsigned GetInterpolatedColor(float x, float y); /// Add or merge a batch. diff --git a/Source/Atomic/Graphics/Text3D/Text3DBitmap.cpp b/Source/Atomic/Graphics/Text3D/Text3DBitmap.cpp index 0d1a441556..9e0882d1b9 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DBitmap.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3DBitmap.cpp @@ -48,7 +48,7 @@ Text3DBitmap::~Text3DBitmap() { } -bool Text3DBitmap::Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize) +bool Text3DBitmap::Load(const unsigned char* fontData, unsigned fontDataSize, float pointSize) { Context* context = font_->GetContext(); @@ -253,7 +253,7 @@ bool Text3DBitmap::Load(Text3DFontFace* fontFace, bool usedGlyphs) for (unsigned i = 0; i < newImages.Size(); ++i) textures_[i] = LoadFaceTexture(newImages[i]); - for (HashMap::ConstIterator i = fontFace->kerningMapping_.Begin(); i != fontFace->kerningMapping_.End(); ++i) + for (HashMap::ConstIterator i = fontFace->kerningMapping_.Begin(); i != fontFace->kerningMapping_.End(); ++i) { unsigned first = (i->first_) >> 16; unsigned second = (i->first_) & 0xffff; @@ -331,7 +331,7 @@ bool Text3DBitmap::Save(Serializer& dest, int pointSize, const String& indentati if (!kerningMapping_.Empty()) { XMLElement kerningsElem = rootElem.CreateChild("kernings"); - for (HashMap::ConstIterator i = kerningMapping_.Begin(); i != kerningMapping_.End(); ++i) + for (HashMap::ConstIterator i = kerningMapping_.Begin(); i != kerningMapping_.End(); ++i) { XMLElement kerningElem = kerningsElem.CreateChild("kerning"); kerningElem.SetInt("first", i->first_ >> 16); diff --git a/Source/Atomic/Graphics/Text3D/Text3DBitmap.h b/Source/Atomic/Graphics/Text3D/Text3DBitmap.h index b3c804a45c..cf48120dbf 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DBitmap.h +++ b/Source/Atomic/Graphics/Text3D/Text3DBitmap.h @@ -42,7 +42,7 @@ class ATOMIC_API Text3DBitmap : public Text3DFontFace ~Text3DBitmap(); /// Load font face. - virtual bool Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize); + virtual bool Load(const unsigned char* fontData, unsigned fontDataSize, float pointSize); /// Load from existed font face, pack used glyphs into smallest texture size and smallest number of texture. bool Load(Text3DFontFace* fontFace, bool usedGlyphs); /// Save as a new bitmap font type in XML format. Return true if successful. diff --git a/Source/Atomic/Graphics/Text3D/Text3DFont.cpp b/Source/Atomic/Graphics/Text3D/Text3DFont.cpp index d6703f7ca9..8930639103 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DFont.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3DFont.cpp @@ -38,8 +38,17 @@ namespace Atomic { -static const int MIN_POINT_SIZE = 1; -static const int MAX_POINT_SIZE = 96; +namespace +{ + /// Convert float to 26.6 fixed-point (as used internally by FreeType) + inline int FloatToFixed(float value) + { + return (int)(value * 64); + } +} + +static const float MIN_POINT_SIZE = 1; +static const float MAX_POINT_SIZE = 96; Text3DFont::Text3DFont(Context* context) : Resource(context), @@ -126,7 +135,7 @@ void Text3DFont::SetScaledGlyphOffset(const Vector2& offset) scaledOffset_ = offset; } -Text3DFontFace* Text3DFont::GetFace(int pointSize) +Text3DFontFace* Text3DFont::GetFace(float pointSize) { // In headless mode, always return null Graphics* graphics = GetSubsystem(); @@ -139,7 +148,9 @@ Text3DFontFace* Text3DFont::GetFace(int pointSize) else pointSize = Clamp(pointSize, MIN_POINT_SIZE, MAX_POINT_SIZE); - HashMap >::Iterator i = faces_.Find(pointSize); + // For outline fonts, we return the nearest size in 1/64th increments, as that's what FreeType supports. + int key = FloatToFixed(pointSize); + HashMap >::Iterator i = faces_.Find(key); if (i != faces_.End()) { if (!i->second_->IsDataLost()) @@ -166,10 +177,10 @@ Text3DFontFace* Text3DFont::GetFace(int pointSize) } } -IntVector2 Text3DFont::GetTotalGlyphOffset(int pointSize) const +IntVector2 Text3DFont::GetTotalGlyphOffset(float pointSize) const { - Vector2 multipliedOffset = (float)pointSize * scaledOffset_; - return absoluteOffset_ + IntVector2((int)multipliedOffset.x_, (int)multipliedOffset.y_); + Vector2 multipliedOffset = pointSize * scaledOffset_; + return absoluteOffset_ + IntVector2((int)(multipliedOffset.x_ + 0.5f), (int)(multipliedOffset.y_ + 0.5f)); } void Text3DFont::ReleaseFaces() @@ -208,23 +219,25 @@ void Text3DFont::LoadParameters() } } -Text3DFontFace* Text3DFont::GetFaceFreeType(int pointSize) +Text3DFontFace* Text3DFont::GetFaceFreeType(float pointSize) { SharedPtr newFace(new Text3DFreeType(this)); if (!newFace->Load(&fontData_[0], fontDataSize_, pointSize)) return 0; - faces_[pointSize] = newFace; + int key = FloatToFixed(pointSize); + faces_[key] = newFace; return newFace; } -Text3DFontFace* Text3DFont::GetFaceBitmap(int pointSize) +Text3DFontFace* Text3DFont::GetFaceBitmap(float pointSize) { SharedPtr newFace(new Text3DBitmap(this)); if (!newFace->Load(&fontData_[0], fontDataSize_, pointSize)) return 0; - faces_[pointSize] = newFace; + int key = FloatToFixed(pointSize); + faces_[key] = newFace; return newFace; } diff --git a/Source/Atomic/Graphics/Text3D/Text3DFont.h b/Source/Atomic/Graphics/Text3D/Text3DFont.h index 316917f246..94c539dcfd 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DFont.h +++ b/Source/Atomic/Graphics/Text3D/Text3DFont.h @@ -66,7 +66,7 @@ class ATOMIC_API Text3DFont : public Resource void SetScaledGlyphOffset(const Vector2& offset); /// Return font face. Pack and render to a texture if not rendered yet. Return null on error. - Text3DFontFace* GetFace(int pointSize); + Text3DFontFace* GetFace(float pointSize); /// Return font type. Text3DFontType GetFontType() const { return fontType_; } @@ -81,7 +81,7 @@ class ATOMIC_API Text3DFont : public Resource const Vector2& GetScaledGlyphOffset() const { return scaledOffset_; } /// Return the total effective offset for a point size. - IntVector2 GetTotalGlyphOffset(int pointSize) const; + IntVector2 GetTotalGlyphOffset(float pointSize) const; /// Release font faces and recreate them next time when requested. Called when font textures lost or global font properties change. void ReleaseFaces(); @@ -90,9 +90,9 @@ class ATOMIC_API Text3DFont : public Resource /// Load font glyph offset parameters from an optional XML file. Called internally when loading TrueType fonts. void LoadParameters(); /// Return font face using FreeType. Called internally. Return null on error. - Text3DFontFace* GetFaceFreeType(int pointSize); + Text3DFontFace* GetFaceFreeType(float pointSize); /// Return bitmap font face. Called internally. Return null on error. - Text3DFontFace* GetFaceBitmap(int pointSize); + Text3DFontFace* GetFaceBitmap(float pointSize); /// Created faces. HashMap > faces_; diff --git a/Source/Atomic/Graphics/Text3D/Text3DFontFace.cpp b/Source/Atomic/Graphics/Text3D/Text3DFontFace.cpp index 7c8bc32d51..49d0d73c9b 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DFontFace.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3DFontFace.cpp @@ -70,7 +70,7 @@ const Text3DFontGlyph* Text3DFontFace::GetGlyph(unsigned c) return 0; } -short Text3DFontFace::GetKerning(unsigned c, unsigned d) const +float Text3DFontFace::GetKerning(unsigned c, unsigned d) const { if (kerningMapping_.Empty()) return 0; @@ -83,7 +83,7 @@ short Text3DFontFace::GetKerning(unsigned c, unsigned d) const unsigned value = (c << 16) + d; - HashMap::ConstIterator i = kerningMapping_.Find(value); + HashMap::ConstIterator i = kerningMapping_.Find(value); if (i != kerningMapping_.End()) return i->second_; diff --git a/Source/Atomic/Graphics/Text3D/Text3DFontFace.h b/Source/Atomic/Graphics/Text3D/Text3DFontFace.h index e917809afb..6fa593251a 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DFontFace.h +++ b/Source/Atomic/Graphics/Text3D/Text3DFontFace.h @@ -52,7 +52,7 @@ struct ATOMIC_API Text3DFontGlyph /// Glyph Y offset from origin. short offsetY_; /// Horizontal advance. - short advanceX_; + float advanceX_; /// Texture page. M_MAX_UNSIGNED if not yet resident on any texture. unsigned page_; /// Used flag. @@ -73,7 +73,7 @@ class ATOMIC_API Text3DFontFace : public RefCounted ~Text3DFontFace(); /// Load font face. - virtual bool Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize) = 0; + virtual bool Load(const unsigned char* fontData, unsigned fontDataSize, float pointSize) = 0; /// Return pointer to the glyph structure corresponding to a character. Return null if glyph not found. virtual const Text3DFontGlyph* GetGlyph(unsigned c); @@ -81,15 +81,15 @@ class ATOMIC_API Text3DFontFace : public RefCounted virtual bool HasMutableGlyphs() const { return false; } /// Return the kerning for a character and the next character. - short GetKerning(unsigned c, unsigned d) const; + float GetKerning(unsigned c, unsigned d) const; /// Return true when one of the texture has a data loss. bool IsDataLost() const; /// Return point size. - int GetPointSize() const { return pointSize_; } + float GetPointSize() const { return pointSize_; } /// Return row height. - int GetRowHeight() const { return rowHeight_; } + float GetRowHeight() const { return rowHeight_; } /// Return textures. const Vector >& GetTextures() const { return textures_; } @@ -106,13 +106,13 @@ class ATOMIC_API Text3DFontFace : public RefCounted /// Glyph mapping. HashMap glyphMapping_; /// Kerning mapping. - HashMap kerningMapping_; + HashMap kerningMapping_; /// Glyph texture pages. Vector > textures_; /// Point size. - int pointSize_; + float pointSize_; /// Row height. - int rowHeight_; + float rowHeight_; }; } diff --git a/Source/Atomic/Graphics/Text3D/Text3DFreeType.cpp b/Source/Atomic/Graphics/Text3D/Text3DFreeType.cpp index 09572af122..48c48f9c6e 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DFreeType.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3DFreeType.cpp @@ -40,9 +40,9 @@ namespace Atomic { -inline int RoundToPixels(FT_Pos value) +inline float FixedToFloat(FT_Pos value) { - return (int)(value >> 6) + (((value & 0x3f) >= 0x20) ? 1 : 0); + return value / 64.0f; } /// FreeType library subsystem. @@ -78,7 +78,9 @@ Text3DFreeType::Text3DFreeType(Text3DFont* font) : face_(0), loadMode_(FT_LOAD_DEFAULT), hasMutableGlyph_(false), - forceAutoHint_(false) + forceAutoHint_(false), + subpixelGlyphPositions_(false), + fontHintLevel_(FONT_HINT_LEVEL_NORMAL) { } @@ -91,7 +93,7 @@ Text3DFreeType::~Text3DFreeType() } } -bool Text3DFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize) +bool Text3DFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, float pointSize) { Context* context = font_->GetContext(); @@ -138,7 +140,7 @@ bool Text3DFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, face_ = face; unsigned numGlyphs = (unsigned)face->num_glyphs; - ATOMIC_LOGDEBUGF("Font face %s (%dpt) has %d glyphs", GetFileName(font_->GetName()).CString(), pointSize, numGlyphs); + ATOMIC_LOGDEBUGF("Font face %s (%fpt) has %d glyphs", GetFileName(font_->GetName()).CString(), pointSize, numGlyphs); PODVector charCodes(numGlyphs + 1, 0); @@ -157,20 +159,34 @@ bool Text3DFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, } // Load each of the glyphs to see the sizes & store other information - loadMode_ = (int)(forceAutoHint_ ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT); - ascender_ = RoundToPixels(face->size->metrics.ascender); - rowHeight_ = RoundToPixels(face->size->metrics.height); + loadMode_ = FT_LOAD_DEFAULT; + if (forceAutoHint_) + { + loadMode_ |= FT_LOAD_FORCE_AUTOHINT; + } + if (GetFontHintLevel() == FONT_HINT_LEVEL_NONE) + { + loadMode_ |= FT_LOAD_NO_HINTING; + } + if (GetFontHintLevel() == FONT_HINT_LEVEL_LIGHT) + { + loadMode_ |= FT_LOAD_TARGET_LIGHT; + } + + ascender_ = FixedToFloat(face->size->metrics.ascender); + rowHeight_ = FixedToFloat(face->size->metrics.height); pointSize_ = pointSize; // Check if the font's OS/2 info gives different (larger) values for ascender & descender TT_OS2* os2Info = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2); if (os2Info) { - int descender = RoundToPixels(face->size->metrics.descender); - ascender_ = Max(ascender_, os2Info->usWinAscent * face->size->metrics.y_ppem / face->units_per_EM); - ascender_ = Max(ascender_, os2Info->sTypoAscender * face->size->metrics.y_ppem / face->units_per_EM); - descender = Max(descender, os2Info->usWinDescent * face->size->metrics.y_ppem / face->units_per_EM); - descender = Max(descender, os2Info->sTypoDescender * face->size->metrics.y_ppem / face->units_per_EM); + float descender = FixedToFloat(face->size->metrics.descender); + float unitsPerEm = face->units_per_EM; + ascender_ = Max(ascender_, os2Info->usWinAscent * face->size->metrics.y_ppem / unitsPerEm); + ascender_ = Max(ascender_, os2Info->sTypoAscender * face->size->metrics.y_ppem / unitsPerEm); + descender = Max(descender, os2Info->usWinDescent * face->size->metrics.y_ppem / unitsPerEm); + descender = Max(descender, os2Info->sTypoDescender * face->size->metrics.y_ppem / unitsPerEm); rowHeight_ = Max(rowHeight_, ascender_ + descender); } @@ -251,7 +267,7 @@ bool Text3DFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, { unsigned leftIndex = deserializer.ReadUShort(); unsigned rightIndex = deserializer.ReadUShort(); - short amount = RoundToPixels(deserializer.ReadShort()); + short amount = FixedToFloat(deserializer.ReadShort()); unsigned leftCharCode = leftIndex < numGlyphs ? charCodes[leftIndex] : 0; unsigned rightCharCode = rightIndex < numGlyphs ? charCodes[rightIndex] : 0; @@ -353,7 +369,19 @@ bool Text3DFreeType::LoadCharGlyph(unsigned charCode, Image* image) fontGlyph.height_ = slot->bitmap.rows; fontGlyph.offsetX_ = slot->bitmap_left; fontGlyph.offsetY_ = ascender_ - slot->bitmap_top; - fontGlyph.advanceX_ = (short)RoundToPixels(slot->metrics.horiAdvance); + + FontHintLevel level = GetFontHintLevel(); + bool subpixel = GetSubpixelGlyphPositions(); + if (level <= FONT_HINT_LEVEL_LIGHT && subpixel && slot->linearHoriAdvance) + { + // linearHoriAdvance is stored in 16.16 fixed point, not the usual 26.6 + fontGlyph.advanceX_ = slot->linearHoriAdvance / 65536.0; + } + else + { + // Round to nearest pixel (only necessary when hinting is disabled) + fontGlyph.advanceX_ = floor(FixedToFloat(slot->metrics.horiAdvance) + 0.5f); + } } int x = 0, y = 0; @@ -371,13 +399,11 @@ bool Text3DFreeType::LoadCharGlyph(unsigned charCode, Image* image) int h = allocator_.GetHeight(); if (!SetupNextTexture(w, h)) { - ATOMIC_LOGWARNINGF("Text3DFreeType::LoadCharGlyph: failed to allocate new %dx%d texture", w, h); return false; } if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y)) { - ATOMIC_LOGWARNINGF("Text3DFreeType::LoadCharGlyph: failed to position char code %u in blank page", charCode); return false; } } diff --git a/Source/Atomic/Graphics/Text3D/Text3DFreeType.h b/Source/Atomic/Graphics/Text3D/Text3DFreeType.h index 8977441e39..9f4193809f 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DFreeType.h +++ b/Source/Atomic/Graphics/Text3D/Text3DFreeType.h @@ -30,6 +30,18 @@ namespace Atomic class FreeTypeLibrary; class Texture2D; +enum FontHintLevel +{ + /// Completely disable font hinting. Output will be blurrier but more "correct". + FONT_HINT_LEVEL_NONE = 0, + + /// Light hinting. FreeType will pixel-align fonts vertically, but not horizontally. + FONT_HINT_LEVEL_LIGHT, + + /// Full hinting, using either the font's own hinting or FreeType's auto-hinter. + FONT_HINT_LEVEL_NORMAL +}; + /// Free type font face description. class ATOMIC_API Text3DFreeType : public Text3DFontFace { @@ -42,7 +54,7 @@ class ATOMIC_API Text3DFreeType : public Text3DFontFace ~Text3DFreeType(); /// Load font face. - virtual bool Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize); + virtual bool Load(const unsigned char* fontData, unsigned fontDataSize, float pointSize); /// Return pointer to the glyph structure corresponding to a character. Return null if glyph not found. virtual const Text3DFontGlyph* GetGlyph(unsigned c); @@ -52,6 +64,18 @@ class ATOMIC_API Text3DFreeType : public Text3DFontFace /// Set whether to force font autohinting instead of using FreeType's TTF bytecode interpreter. void SetForceAutoHint(bool enable) { forceAutoHint_ = enable; } + /// Return the current FreeType font hinting level. + FontHintLevel GetFontHintLevel() const { return fontHintLevel_; } + + /// Set the hinting level used by FreeType fonts. + void SetFontHintLevel(FontHintLevel level) { fontHintLevel_ = level; } + + // Return whether text glyphs can have fractional positions. + bool GetSubpixelGlyphPositions() const { return subpixelGlyphPositions_; } + + /// Set whether text glyphs can have fractional positions. Default is false (pixel-aligned). + void SetSubpixelGlyphPositions(bool enable) { subpixelGlyphPositions_ = enable; } + private: /// Setup next texture. bool SetupNextTexture(int textureWidth, int textureHeight); @@ -65,13 +89,15 @@ class ATOMIC_API Text3DFreeType : public Text3DFontFace /// Load mode. int loadMode_; /// Ascender. - int ascender_; + float ascender_; /// Has mutable glyph. bool hasMutableGlyph_; /// Glyph area allocator. AreaAllocator allocator_; bool forceAutoHint_; + bool subpixelGlyphPositions_; + FontHintLevel fontHintLevel_; }; } diff --git a/Source/Atomic/Graphics/Text3D/Text3DText.cpp b/Source/Atomic/Graphics/Text3D/Text3DText.cpp index 403cbd1d7c..f37a306ba4 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DText.cpp +++ b/Source/Atomic/Graphics/Text3D/Text3DText.cpp @@ -111,7 +111,7 @@ void Text3DText::RegisterObject(Context* context) ATOMIC_COPY_BASE_ATTRIBUTES(Animatable); ATOMIC_UPDATE_ATTRIBUTE_DEFAULT_VALUE("Use Derived Opacity", false); ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Font", GetFontAttr, SetFontAttr, ResourceRef, ResourceRef(Text3DFont::GetTypeStatic()), AM_FILE); - ATOMIC_ATTRIBUTE("Font Size", int, fontSize_, TEXT3D_DEFAULT_FONT_SIZE, AM_FILE); + ATOMIC_ATTRIBUTE("Font Size", float, fontSize_, TEXT3D_DEFAULT_FONT_SIZE, AM_FILE); ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Text", GetTextAttr, SetTextAttr, String, String::EMPTY, AM_FILE); ATOMIC_ENUM_ATTRIBUTE("Text Alignment", textAlignment_, horizontalAlignments, HA_LEFT, AM_FILE); ATOMIC_ATTRIBUTE("Row Spacing", float, rowSpacing_, 1.0f, AM_FILE); @@ -233,12 +233,12 @@ void Text3DText::GetBatches(PODVector& batches, PODVector& v Text3DBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData); batch.SetColor(selectionColor_); - IntVector2 currentStart = charLocations_[selectionStart_].position_; - IntVector2 currentEnd = currentStart; + Vector2 currentStart = charLocations_[selectionStart_].position_; + Vector2 currentEnd = currentStart; for (unsigned i = selectionStart_; i < selectionStart_ + selectionLength_; ++i) { // Check if row changes, and start a new quad in that case - if (charLocations_[i].size_ != IntVector2::ZERO) + if (charLocations_[i].size_ != Vector2::ZERO) { if (charLocations_[i].position_.y_ != currentStart.y_) { @@ -297,7 +297,7 @@ void Text3DText::GetBatches(PODVector& batches, PODVector& v { float x = Cos(angle * i) * floatThickness; float y = Sin(angle * i) * floatThickness; - ConstructBatch(pageBatch, pageGlyphLocation, (int)x, (int)y, &effectColor_, effectDepthBias_); + ConstructBatch(pageBatch, pageGlyphLocation, x, y, &effectColor_, effectDepthBias_); } } else @@ -341,13 +341,13 @@ void Text3DText::OnIndentSet() charLocationsDirty_ = true; } -bool Text3DText::SetFont(const String& fontName, int size) +bool Text3DText::SetFont(const String& fontName, float size) { ResourceCache* cache = GetSubsystem(); return SetFont(cache->GetResource(fontName), size); } -bool Text3DText::SetFont(Text3DFont* font, int size) +bool Text3DText::SetFont(Text3DFont* font, float size) { if (!font) { @@ -365,7 +365,7 @@ bool Text3DText::SetFont(Text3DFont* font, int size) return true; } -bool Text3DText::SetFontSize(int size) +bool Text3DText::SetFontSize(float size) { // Initial font must be set if (!font_) @@ -512,29 +512,29 @@ void Text3DText::SetEffectDepthBias(float bias) effectDepthBias_ = bias; } -int Text3DText::GetRowWidth(unsigned index) const +float Text3DText::GetRowWidth(unsigned index) const { return index < rowWidths_.Size() ? rowWidths_[index] : 0; } -IntVector2 Text3DText::GetCharPosition(unsigned index) +Vector2 Text3DText::GetCharPosition(unsigned index) { if (charLocationsDirty_) UpdateCharLocations(); if (charLocations_.Empty()) - return IntVector2::ZERO; + return Vector2::ZERO; // For convenience, return the position of the text ending if index exceeded if (index > charLocations_.Size() - 1) index = charLocations_.Size() - 1; return charLocations_[index].position_; } -IntVector2 Text3DText::GetCharSize(unsigned index) +Vector2 Text3DText::GetCharSize(unsigned index) { if (charLocationsDirty_) UpdateCharLocations(); if (charLocations_.Size() < 2) - return IntVector2::ZERO; + return Vector2::ZERO; // For convenience, return the size of the last char if index exceeded (last size entry is zero) if (index > charLocations_.Size() - 2) index = charLocations_.Size() - 2; @@ -583,7 +583,7 @@ void Text3DText::UpdateText(bool onResize) int width = 0; int height = 0; int rowWidth = 0; - int rowHeight = (int)(rowSpacing_ * rowHeight_); + int rowHeight = (int)(rowSpacing_ * rowHeight_ + 0.5f); // First see if the text must be split up if (!wordWrap_) @@ -754,7 +754,7 @@ void Text3DText::UpdateCharLocations() return; fontFace_ = face; - int rowHeight = (int)(rowSpacing_ * rowHeight_); + int rowHeight = (int)(rowSpacing_ * rowHeight_ + 0.5f); // Store position & size of each character, and locations per texture page unsigned numChars = unicodeText_.Size(); @@ -767,19 +767,19 @@ void Text3DText::UpdateCharLocations() unsigned rowIndex = 0; unsigned lastFilled = 0; - int x = GetRowStartPosition(rowIndex) + offset.x_; - int y = offset.y_; + float x = floor(GetRowStartPosition(rowIndex) + offset.x_ + 0.5f); + float y = floor(offset.y_ + 0.5f); for (unsigned i = 0; i < printText_.Size(); ++i) { Text3DCharLocation loc; - loc.position_ = IntVector2(x, y); + loc.position_ = Vector2(x, y); unsigned c = printText_[i]; if (c != '\n') { const Text3DFontGlyph* glyph = face->GetGlyph(c); - loc.size_ = IntVector2(glyph ? glyph->advanceX_ : 0, rowHeight_); + loc.size_ = Vector2(glyph ? glyph->advanceX_ : 0, rowHeight_); if (glyph) { // Store glyph's location for rendering. Verify that glyph page is valid @@ -792,7 +792,7 @@ void Text3DText::UpdateCharLocations() } else { - loc.size_ = IntVector2::ZERO; + loc.size_ = Vector2::ZERO; x = GetRowStartPosition(++rowIndex); y += rowHeight; } @@ -806,8 +806,8 @@ void Text3DText::UpdateCharLocations() lastFilled = printToText_[i] + 1; } // Store the ending position - charLocations_[numChars].position_ = IntVector2(x, y); - charLocations_[numChars].size_ = IntVector2::ZERO; + charLocations_[numChars].position_ = Vector2(x, y); + charLocations_[numChars].size_ = Vector2::ZERO; charLocationsDirty_ = false; } @@ -832,7 +832,7 @@ void Text3DText::ValidateSelection() int Text3DText::GetRowStartPosition(unsigned rowIndex) const { - int rowWidth = 0; + float rowWidth = 0; if (rowIndex < rowWidths_.Size()) rowWidth = rowWidths_[rowIndex]; @@ -866,7 +866,7 @@ void Text3DText::SetIndentSpacing(int indentSpacing) OnIndentSet(); } -void Text3DText::ConstructBatch(Text3DBatch& pageBatch, const PODVector& pageGlyphLocation, int dx, int dy, Color* color, +void Text3DText::ConstructBatch(Text3DBatch& pageBatch, const PODVector& pageGlyphLocation, float dx, float dy, Color* color, float depthBias) { unsigned startDataSize = pageBatch.vertexData_->Size(); diff --git a/Source/Atomic/Graphics/Text3D/Text3DText.h b/Source/Atomic/Graphics/Text3D/Text3DText.h index 74223f8d2a..93b4509c8a 100644 --- a/Source/Atomic/Graphics/Text3D/Text3DText.h +++ b/Source/Atomic/Graphics/Text3D/Text3DText.h @@ -28,7 +28,7 @@ namespace Atomic { -static const int TEXT3D_DEFAULT_FONT_SIZE = 12; +static const float TEXT3D_DEFAULT_FONT_SIZE = 12; class Text3DFont; class Text3DFontFace; @@ -46,16 +46,16 @@ enum Text3DTextEffect struct Text3DCharLocation { /// Position. - IntVector2 position_; + Vector2 position_; /// Size. - IntVector2 size_; + Vector2 size_; }; /// Glyph and its location within the text. Used when preparing text rendering. struct Text3DGlyphLocation { /// Construct. - Text3DGlyphLocation(int x, int y, const Text3DFontGlyph* glyph) : + Text3DGlyphLocation(float x, float y, const Text3DFontGlyph* glyph) : x_(x), y_(y), glyph_(glyph) @@ -63,9 +63,9 @@ struct Text3DGlyphLocation } /// X coordinate. - int x_; + float x_; /// Y coordinate. - int y_; + float y_; /// Glyph. const Text3DFontGlyph* glyph_; }; @@ -121,11 +121,11 @@ class ATOMIC_API Text3DText : public Animatable virtual void OnIndentSet(); /// Set font by looking from resource cache by name and font size. Return true if successful. - bool SetFont(const String& fontName, int size = TEXT3D_DEFAULT_FONT_SIZE); + bool SetFont(const String& fontName, float size = TEXT3D_DEFAULT_FONT_SIZE); /// Set font and font size. Return true if successful. - bool SetFont(Text3DFont* font, int size = TEXT3D_DEFAULT_FONT_SIZE); + bool SetFont(Text3DFont* font, float size = TEXT3D_DEFAULT_FONT_SIZE); /// Set font size only while retaining the existing font. Return true if successful. - bool SetFontSize(int size); + bool SetFontSize(float size); /// Set text. Text is assumed to be either ASCII or UTF8-encoded. void SetText(const String& text); /// Set row alignment. @@ -159,7 +159,7 @@ class ATOMIC_API Text3DText : public Animatable Text3DFont* GetFont() const { return font_; } /// Return font size. - int GetFontSize() const { return fontSize_; } + float GetFontSize() const { return fontSize_; } /// Return text. const String& GetText() const { return text_; } @@ -204,7 +204,7 @@ class ATOMIC_API Text3DText : public Animatable const Color& GetEffectColor() const { return effectColor_; } /// Return row height. - int GetRowHeight() const { return rowHeight_; } + float GetRowHeight() const { return rowHeight_; } /// Return number of rows. unsigned GetNumRows() const { return rowWidths_.Size(); } @@ -213,11 +213,11 @@ class ATOMIC_API Text3DText : public Animatable unsigned GetNumChars() const { return unicodeText_.Size(); } /// Return width of row by index. - int GetRowWidth(unsigned index) const; + float GetRowWidth(unsigned index) const; /// Return position of character by index relative to the text element origin. - IntVector2 GetCharPosition(unsigned index); + Vector2 GetCharPosition(unsigned index); /// Return size of character by index. - IntVector2 GetCharSize(unsigned index); + Vector2 GetCharSize(unsigned index); /// Set text effect Z bias. Zero by default, adjusted only in 3D mode. void SetEffectDepthBias(float bias); @@ -370,7 +370,7 @@ class ATOMIC_API Text3DText : public Animatable int GetRowStartPosition(unsigned rowIndex) const; /// Contruct batch. void ConstructBatch - (Text3DBatch& pageBatch, const PODVector& pageGlyphLocation, int dx = 0, int dy = 0, Color* color = 0, + (Text3DBatch& pageBatch, const PODVector& pageGlyphLocation, float dx = 0, float dy = 0, Color* color = 0, float depthBias = 0.0f); /// Font. @@ -378,7 +378,7 @@ class ATOMIC_API Text3DText : public Animatable /// Current face. WeakPtr fontFace_; /// Font size. - int fontSize_; + float fontSize_; /// UTF-8 encoded text. String text_; /// Row alignment. @@ -410,7 +410,7 @@ class ATOMIC_API Text3DText : public Animatable /// Text effect Z bias. float effectDepthBias_; /// Row height. - int rowHeight_; + float rowHeight_; /// Text as Unicode characters. PODVector unicodeText_; /// Text modified into printed form. @@ -418,7 +418,7 @@ class ATOMIC_API Text3DText : public Animatable /// Mapping of printed form back to original char indices. PODVector printToText_; /// Row widths. - PODVector rowWidths_; + PODVector rowWidths_; /// Glyph locations per each texture in the font. Vector > pageGlyphLocations_; /// Cached locations of each character in the text. diff --git a/Source/Atomic/Graphics/Texture.cpp b/Source/Atomic/Graphics/Texture.cpp index 7406fe3a82..25594e8a8a 100644 --- a/Source/Atomic/Graphics/Texture.cpp +++ b/Source/Atomic/Graphics/Texture.cpp @@ -56,7 +56,7 @@ static const char* filterModeNames[] = }; Texture::Texture(Context* context) : - Resource(context), + ResourceWithMetadata(context), GPUObject(GetSubsystem()), shaderResourceView_(0), sampler_(0), @@ -204,8 +204,8 @@ void Texture::SetParameters(XMLFile* file) void Texture::SetParameters(const XMLElement& element) { - XMLElement paramElem = element.GetChild(); - while (paramElem) + LoadMetadataFromXML(element); + for (XMLElement paramElem = element.GetChild(); paramElem; paramElem = paramElem.GetNext()) { String name = paramElem.GetName(); @@ -248,8 +248,6 @@ void Texture::SetParameters(const XMLElement& element) if (name == "srgb") SetSRGB(paramElem.GetBool("enable")); - - paramElem = paramElem.GetNext(); } } diff --git a/Source/Atomic/Graphics/Texture.h b/Source/Atomic/Graphics/Texture.h index c38e259cce..ed50c82a6a 100644 --- a/Source/Atomic/Graphics/Texture.h +++ b/Source/Atomic/Graphics/Texture.h @@ -36,9 +36,9 @@ class XMLElement; class XMLFile; /// Base class for texture resources. -class ATOMIC_API Texture : public Resource, public GPUObject +class ATOMIC_API Texture : public ResourceWithMetadata, public GPUObject { - ATOMIC_OBJECT(Texture, Resource) + ATOMIC_OBJECT(Texture, ResourceWithMetadata) public: /// Construct. @@ -116,7 +116,7 @@ class ATOMIC_API Texture : public Resource, public GPUObject /// Return whether rendertarget mipmap levels need regenration. bool GetLevelsDirty() const { return levelsDirty_; } - + /// Return backup texture. Texture* GetBackupTexture() const { return backupTexture_; } diff --git a/Source/Atomic/Graphics/VertexBuffer.cpp b/Source/Atomic/Graphics/VertexBuffer.cpp index 8ad2a813ea..bb1ce9ca53 100644 --- a/Source/Atomic/Graphics/VertexBuffer.cpp +++ b/Source/Atomic/Graphics/VertexBuffer.cpp @@ -202,4 +202,15 @@ unsigned VertexBuffer::GetVertexSize(unsigned elementMask) return size; } -} \ No newline at end of file +void VertexBuffer::UpdateOffsets(PODVector& elements) +{ + unsigned elementOffset = 0; + + for (PODVector::Iterator i = elements.Begin(); i != elements.End(); ++i) + { + i->offset_ = elementOffset; + elementOffset += ELEMENT_TYPESIZES[i->type_]; + } +} + +} diff --git a/Source/Atomic/Graphics/VertexBuffer.h b/Source/Atomic/Graphics/VertexBuffer.h index 4b6f465705..c72e498191 100644 --- a/Source/Atomic/Graphics/VertexBuffer.h +++ b/Source/Atomic/Graphics/VertexBuffer.h @@ -129,6 +129,9 @@ class ATOMIC_API VertexBuffer : public Object, public GPUObject /// Return vertex size for a legacy vertex element bitmask. static unsigned GetVertexSize(unsigned elementMask); + /// Update offsets of vertex elements. + static void UpdateOffsets(PODVector& elements); + private: /// Update offsets of vertex elements. void UpdateOffsets(); diff --git a/Source/Atomic/Graphics/View.cpp b/Source/Atomic/Graphics/View.cpp index 01f580d19b..83267f4b5c 100644 --- a/Source/Atomic/Graphics/View.cpp +++ b/Source/Atomic/Graphics/View.cpp @@ -655,12 +655,16 @@ void View::Render() { BlitFramebuffer(currentRenderTarget_->GetParentTexture(), renderTarget_, false); currentRenderTarget_ = renderTarget_; + lastCustomDepthSurface_ = 0; } graphics_->SetRenderTarget(0, currentRenderTarget_); for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i) graphics_->SetRenderTarget(i, (RenderSurface*)0); - graphics_->SetDepthStencil(GetDepthStencil(currentRenderTarget_)); + + // If a custom depth surface was used, use it also for debug rendering + graphics_->SetDepthStencil(lastCustomDepthSurface_ ? lastCustomDepthSurface_ : GetDepthStencil(currentRenderTarget_)); + IntVector2 rtSizeNow = graphics_->GetRenderTargetDimensions(); IntRect viewport = (currentRenderTarget_ == renderTarget_) ? viewRect_ : IntRect(0, 0, rtSizeNow.x_, rtSizeNow.y_); @@ -1799,7 +1803,8 @@ void View::SetRenderTargets(RenderPathCommand& command) if (depthTexture) { useCustomDepth = true; - graphics_->SetDepthStencil(GetRenderSurfaceFromTexture(depthTexture)); + lastCustomDepthSurface_ = GetRenderSurfaceFromTexture(depthTexture); + graphics_->SetDepthStencil(lastCustomDepthSurface_); } } @@ -1978,6 +1983,7 @@ void View::AllocateScreenBuffers() bool needSubstitute = false; unsigned numViewportTextures = 0; depthOnlyDummyTexture_ = 0; + lastCustomDepthSurface_ = 0; // Check for commands with special meaning: has custom depth, renders a scene pass to other than the destination viewport, // read the viewport, or pingpong between viewport textures. These may trigger the need to substitute the destination RT diff --git a/Source/Atomic/Graphics/View.h b/Source/Atomic/Graphics/View.h index 7272458f01..3fe573abbc 100644 --- a/Source/Atomic/Graphics/View.h +++ b/Source/Atomic/Graphics/View.h @@ -336,6 +336,8 @@ class ATOMIC_API View : public Object Texture* viewportTextures_[MAX_VIEWPORT_TEXTURES]; /// Color rendertarget active for the current renderpath command. RenderSurface* currentRenderTarget_; + /// Last used custom depth render surface. + RenderSurface* lastCustomDepthSurface_; /// Texture containing the latest viewport texture. Texture* currentViewportTexture_; /// Dummy texture for D3D9 depth only rendering. diff --git a/Source/Atomic/IK/IKSolver.cpp b/Source/Atomic/IK/IKSolver.cpp index 4dcbc07de6..c1e8ee035e 100644 --- a/Source/Atomic/IK/IKSolver.cpp +++ b/Source/Atomic/IK/IKSolver.cpp @@ -54,6 +54,8 @@ static bool ChildrenHaveEffector(const Node* node) if (ChildrenHaveEffector(it->Get())) return true; } + + return false; } // ---------------------------------------------------------------------------- diff --git a/Source/Atomic/IO/Compression.cpp b/Source/Atomic/IO/Compression.cpp index 6e4405a464..8f2fb94142 100644 --- a/Source/Atomic/IO/Compression.cpp +++ b/Source/Atomic/IO/Compression.cpp @@ -44,7 +44,7 @@ unsigned CompressData(void* dest, const void* src, unsigned srcSize) if (!dest || !src || !srcSize) return 0; else - return (unsigned)LZ4_compressHC((const char*)src, (char*)dest, srcSize); + return (unsigned)LZ4_compress_HC((const char*)src, (char*)dest, srcSize, LZ4_compressBound(srcSize), 0); } unsigned DecompressData(void* dest, const void* src, unsigned destSize) @@ -73,7 +73,7 @@ bool CompressStream(Serializer& dest, Deserializer& src) if (src.Read(srcBuffer, srcSize) != srcSize) return false; - unsigned destSize = (unsigned)LZ4_compressHC((const char*)srcBuffer.Get(), (char*)destBuffer.Get(), srcSize); + unsigned destSize = (unsigned)LZ4_compress_HC((const char*)srcBuffer.Get(), (char*)destBuffer.Get(), srcSize, LZ4_compressBound(srcSize), 0); bool success = true; success &= dest.WriteUInt(srcSize); success &= dest.WriteUInt(destSize); diff --git a/Source/Atomic/IO/FileSystem.cpp b/Source/Atomic/IO/FileSystem.cpp index 35599b1ff1..0b5fb1bafc 100644 --- a/Source/Atomic/IO/FileSystem.cpp +++ b/Source/Atomic/IO/FileSystem.cpp @@ -76,7 +76,7 @@ extern "C" const char* SDL_Android_GetFilesDir(); char** SDL_Android_GetFileList(const char* path, int* count); void SDL_Android_FreeFileList(char*** array, int* count); -#elif IOS +#elif defined(IOS) || defined(TVOS) const char* SDL_IOS_GetResourceDir(); const char* SDL_IOS_GetDocumentsDir(); #endif @@ -89,6 +89,9 @@ namespace Atomic int DoSystemCommand(const String& commandLine, bool redirectToLog, Context* context) { +#ifdef TVOS + return -1; +#else #if !defined(__EMSCRIPTEN__) && !defined(MINI_URHO) if (!redirectToLog) #endif @@ -139,10 +142,14 @@ int DoSystemCommand(const String& commandLine, bool redirectToLog, Context* cont return exitCode; #endif +#endif } int DoSystemRun(const String& fileName, const Vector& arguments) { +#ifdef TVOS + return -1; +#else String fixedFileName = GetNativePath(fileName); #ifdef _WIN32 @@ -193,6 +200,7 @@ int DoSystemRun(const String& fileName, const Vector& arguments) else return -1; #endif +#endif } /// Base class for async execution requests. @@ -700,7 +708,7 @@ String FileSystem::GetProgramDir() const // This is an internal directory specifier pointing to the assets in the .apk // Files from this directory will be opened using special handling return APK; -#elif defined(IOS) +#elif defined(IOS) || defined(TVOS) return AddTrailingSlash(SDL_IOS_GetResourceDir()); #elif defined(_WIN32) wchar_t exeName[MAX_PATH]; @@ -730,7 +738,7 @@ String FileSystem::GetUserDocumentsDir() const { #if defined(__ANDROID__) return AddTrailingSlash(SDL_Android_GetFilesDir()); -#elif defined(IOS) +#elif defined(IOS) || defined(TVOS) return AddTrailingSlash(SDL_IOS_GetDocumentsDir()); #elif defined(_WIN32) wchar_t pathName[MAX_PATH]; diff --git a/Source/Atomic/IO/FileWatcher.cpp b/Source/Atomic/IO/FileWatcher.cpp index ee7d5c8c4a..bb354228e7 100644 --- a/Source/Atomic/IO/FileWatcher.cpp +++ b/Source/Atomic/IO/FileWatcher.cpp @@ -36,7 +36,7 @@ extern "C" // Need read/close for inotify #include "unistd.h" } -#elif defined(__APPLE__) && !defined(IOS) +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) extern "C" { #include "../IO/MacFileWatcher.h" @@ -58,7 +58,7 @@ FileWatcher::FileWatcher(Context* context) : #ifdef ATOMIC_FILEWATCHER #ifdef __linux__ watchHandle_ = inotify_init(); -#elif defined(__APPLE__) && !defined(IOS) +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) supported_ = IsFileWatcherSupported(); #endif #endif @@ -176,7 +176,7 @@ bool FileWatcher::StartWatching(const String& pathName, bool watchSubDirs) ATOMIC_LOGDEBUG("Started watching path " + pathName); return true; } -#elif defined(__APPLE__) && !defined(IOS) +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) if (!supported_) { ATOMIC_LOGERROR("Individual file watching not supported by this OS version, can not start watching path " + pathName); @@ -225,7 +225,7 @@ void FileWatcher::StopWatching() fileSystem_->Delete(dummyFileName); #endif -#if defined(__APPLE__) && !defined(IOS) +#if defined(__APPLE__) && !defined(IOS) && !defined(TVOS) // Our implementation of file watcher requires the thread to be stopped first before closing the watcher Stop(); #endif @@ -236,7 +236,7 @@ void FileWatcher::StopWatching() for (HashMap::Iterator i = dirHandle_.Begin(); i != dirHandle_.End(); ++i) inotify_rm_watch(watchHandle_, i->first_); dirHandle_.Clear(); -#elif defined(__APPLE__) && !defined(IOS) +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) CloseFileWatcher(watcher_); #endif @@ -326,7 +326,7 @@ void FileWatcher::ThreadFunction() i += sizeof(inotify_event) + event->len; } } -#elif defined(__APPLE__) && !defined(IOS) +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) while (shouldRun_) { Time::Sleep(100); diff --git a/Source/Atomic/IO/FileWatcher.h b/Source/Atomic/IO/FileWatcher.h index aa7f89ba1f..20b67f114a 100644 --- a/Source/Atomic/IO/FileWatcher.h +++ b/Source/Atomic/IO/FileWatcher.h @@ -90,7 +90,7 @@ class ATOMIC_API FileWatcher : public Object, public Thread /// Linux inotify needs a handle. int watchHandle_; -#elif defined(__APPLE__) && !defined(IOS) +#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS) /// Flag indicating whether the running OS supports individual file watching. bool supported_; diff --git a/Source/Atomic/IO/Log.cpp b/Source/Atomic/IO/Log.cpp index f4c395aa0e..e165eab1f0 100644 --- a/Source/Atomic/IO/Log.cpp +++ b/Source/Atomic/IO/Log.cpp @@ -36,7 +36,7 @@ #ifdef __ANDROID__ #include #endif -#ifdef IOS +#if defined(IOS) || defined(TVOS) extern "C" void SDL_IOS_LogMessage(const char* message); #endif @@ -80,7 +80,7 @@ Log::~Log() void Log::Open(const String& fileName) { -#if !defined(__ANDROID__) && !defined(IOS) +#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS) if (fileName.Empty()) return; if (logFile_ && logFile_->IsOpen()) @@ -104,7 +104,7 @@ void Log::Open(const String& fileName) void Log::Close() { -#if !defined(__ANDROID__) && !defined(IOS) +#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS) if (logFile_ && logFile_->IsOpen()) { logFile_->Close(); @@ -173,7 +173,7 @@ void Log::Write(int level, const String& message) #if defined(__ANDROID__) int androidLevel = ANDROID_LOG_DEBUG + level; __android_log_print(androidLevel, "Atomic", "%s", message.CString()); -#elif defined(IOS) +#elif defined(IOS) || defined(TVOS) SDL_IOS_LogMessage(message.CString()); #else if (logInstance->quiet_) @@ -232,7 +232,7 @@ void Log::WriteRaw(const String& message, bool error) } else __android_log_print(error ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "Atomic", "%s", message.CString()); -#elif defined(IOS) +#elif defined(IOS) || defined(TVOS) SDL_IOS_LogMessage(message.CString()); #else if (logInstance->quiet_) diff --git a/Source/Atomic/Input/Input.cpp b/Source/Atomic/Input/Input.cpp index 1438fa12db..297a62387e 100644 --- a/Source/Atomic/Input/Input.cpp +++ b/Source/Atomic/Input/Input.cpp @@ -53,8 +53,7 @@ extern "C" int SDL_AddTouch(SDL_TouchID touchID, const char* name); // Use a "click inside window to focus" mechanism on desktop platforms when the mouse cursor is hidden -// TODO: For now, in this particular case only, treat all the ARM on Linux as "desktop" (e.g. RPI, odroid, etc), revisit this again when we support "mobile" ARM on Linux -#if defined(_WIN32) || (defined(__APPLE__) && !defined(IOS)) || (defined(__linux__) && !defined(__ANDROID__)) +#if defined(_WIN32) || (defined(__APPLE__) && !defined(IOS) && !defined(TVOS)) || (defined(__linux__) && !defined(__ANDROID__)) #define REQUIRE_CLICK_TO_FOCUS #endif @@ -413,6 +412,7 @@ Input::Input(Context* context) : mouseButtonPress_(0), lastVisibleMousePosition_(MOUSE_POSITION_OFFSCREEN), mouseMoveWheel_(0), + inputScale_(Vector2::ONE), windowID_(0), toggleFullscreen_(true), // ATOMIC BEGIN @@ -2522,8 +2522,8 @@ void Input::HandleSDLEvent(void* sdlEvent) case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_RESTORED: -#if defined(IOS) || defined (__ANDROID__) - // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet. Apply them now +#if defined(IOS) || defined(TVOS) || defined (__ANDROID__) + // On iOS/tvOS we never lose the GL context, but may have done GPU object changes that could not be applied yet. Apply them now // On Android the old GL context may be lost already, restore GPU objects to the new GL context graphics_->Restore(); #endif diff --git a/Source/Atomic/Input/Input.h b/Source/Atomic/Input/Input.h index b0ecc2a7ab..09ddad079f 100644 --- a/Source/Atomic/Input/Input.h +++ b/Source/Atomic/Input/Input.h @@ -288,6 +288,8 @@ class ATOMIC_API Input : public Object int GetMouseMoveY() const; /// Return mouse wheel movement since last frame. int GetMouseMoveWheel() const { return mouseMoveWheel_; } + /// Return input coordinate scaling. Should return non-unity on High DPI display. + Vector2 GetInputScale() const { return inputScale_; } /// Return number of active finger touches. unsigned GetNumTouches() const { return touches_.Size(); } diff --git a/Source/Atomic/Math/MathDefs.h b/Source/Atomic/Math/MathDefs.h index e764caee8a..a7fee90a3d 100644 --- a/Source/Atomic/Math/MathDefs.h +++ b/Source/Atomic/Math/MathDefs.h @@ -91,6 +91,13 @@ inline T Abs(T value) { return value >= 0.0 ? value : -value; } template inline T Sign(T value) { return value > 0.0 ? 1.0 : (value < 0.0 ? -1.0 : 0.0); } +/// Return a representation of the specified floating-point value as a single format bit layout. +inline unsigned FloatToRawIntBits(float value) +{ + unsigned u = *((unsigned*)&value); + return u; +} + /// Check whether a floating point value is NaN. /// Use a workaround for GCC, see https://github.com/urho3d/Urho3D/issues/655 #ifndef __GNUC__ @@ -99,7 +106,7 @@ inline bool IsNaN(float value) { return value != value; } inline bool IsNaN(float value) { - unsigned u = *(unsigned*)(&value); + unsigned u = FloatToRawIntBits(value); return (u & 0x7fffffff) > 0x7f800000; } @@ -232,7 +239,7 @@ inline float RandomNormal(float meanValue, float variance) { return RandStandard /// Convert float to half float. From https://gist.github.com/martinkallman/5049614 inline unsigned short FloatToHalf(float value) { - unsigned inu = *((unsigned*)&value); + unsigned inu = FloatToRawIntBits(value); unsigned t1 = inu & 0x7fffffff; // Non-sign bits unsigned t2 = inu & 0x80000000; // Sign bit unsigned t3 = inu & 0x7f800000; // Exponent diff --git a/Source/Atomic/Math/Matrix3.h b/Source/Atomic/Math/Matrix3.h index eb302021ee..5895137ce5 100644 --- a/Source/Atomic/Math/Matrix3.h +++ b/Source/Atomic/Math/Matrix3.h @@ -222,7 +222,17 @@ class ATOMIC_API Matrix3 ); } - /// Return transpose. + /// Return the scaling part with the sign. Reference rotation matrix is required to avoid ambiguity. + Vector3 SignedScale(const Matrix3& rotation) const + { + return Vector3( + rotation.m00_ * m00_ + rotation.m10_ * m10_ + rotation.m20_ * m20_, + rotation.m01_ * m01_ + rotation.m11_ * m11_ + rotation.m21_ * m21_, + rotation.m02_ * m02_ + rotation.m12_ * m12_ + rotation.m22_ * m22_ + ); + } + + /// Return transposed. Matrix3 Transpose() const { return Matrix3( @@ -275,6 +285,15 @@ class ATOMIC_API Matrix3 /// Return float data. const float* Data() const { return &m00_; } + /// Return matrix element. + float Element(unsigned i, unsigned j) const { return Data()[i * 3 + j]; } + + /// Return matrix row. + Vector3 Row(unsigned i) const { return Vector3(Element(i, 0), Element(i, 1), Element(i, 2)); } + + /// Return matrix column. + Vector3 Column(unsigned j) const { return Vector3(Element(0, j), Element(1, j), Element(2, j)); } + /// Return as string. String ToString() const; diff --git a/Source/Atomic/Math/Matrix3x4.h b/Source/Atomic/Math/Matrix3x4.h index 4ab79f3495..53d8c507d6 100644 --- a/Source/Atomic/Math/Matrix3x4.h +++ b/Source/Atomic/Math/Matrix3x4.h @@ -665,6 +665,16 @@ class ATOMIC_API Matrix3x4 ); } + /// Return the scaling part with the sign. Reference rotation matrix is required to avoid ambiguity. + Vector3 SignedScale(const Matrix3& rotation) const + { + return Vector3( + rotation.m00_ * m00_ + rotation.m10_ * m10_ + rotation.m20_ * m20_, + rotation.m01_ * m01_ + rotation.m11_ * m11_ + rotation.m21_ * m21_, + rotation.m02_ * m02_ + rotation.m12_ * m12_ + rotation.m22_ * m22_ + ); + } + /// Test for equality with another matrix with epsilon. bool Equals(const Matrix3x4& rhs) const { @@ -682,12 +692,22 @@ class ATOMIC_API Matrix3x4 /// Return decomposition to translation, rotation and scale. void Decompose(Vector3& translation, Quaternion& rotation, Vector3& scale) const; + /// Return inverse. Matrix3x4 Inverse() const; /// Return float data. const float* Data() const { return &m00_; } + /// Return matrix element. + float Element(unsigned i, unsigned j) const { return Data()[i * 4 + j]; } + + /// Return matrix row. + Vector4 Row(unsigned i) const { return Vector4(Element(i, 0), Element(i, 1), Element(i, 2), Element(i, 3)); } + + /// Return matrix column. + Vector3 Column(unsigned j) const { return Vector3(Element(0, j), Element(1, j), Element(2, j)); } + /// Return as string. String ToString() const; diff --git a/Source/Atomic/Math/Matrix4.h b/Source/Atomic/Math/Matrix4.h index c35d018c64..9e2ed3fc61 100644 --- a/Source/Atomic/Math/Matrix4.h +++ b/Source/Atomic/Math/Matrix4.h @@ -96,7 +96,7 @@ class ATOMIC_API Matrix4 #endif } - /// Copy-cnstruct from a 3x3 matrix and set the extra elements to identity. + /// Copy-construct from a 3x3 matrix and set the extra elements to identity. Matrix4(const Matrix3& matrix) : m00_(matrix.m00_), m01_(matrix.m01_), @@ -557,7 +557,7 @@ class ATOMIC_API Matrix4 /// Return the rotation part. Quaternion Rotation() const { return Quaternion(RotationMatrix()); } - /// Return the scaling part + /// Return the scaling part. Vector3 Scale() const { return Vector3( @@ -567,7 +567,17 @@ class ATOMIC_API Matrix4 ); } - /// Return transpose + /// Return the scaling part with the sign. Reference rotation matrix is required to avoid ambiguity. + Vector3 SignedScale(const Matrix3& rotation) const + { + return Vector3( + rotation.m00_ * m00_ + rotation.m10_ * m10_ + rotation.m20_ * m20_, + rotation.m01_ * m01_ + rotation.m11_ * m11_ + rotation.m21_ * m21_, + rotation.m02_ * m02_ + rotation.m12_ * m12_ + rotation.m22_ * m22_ + ); + } + + /// Return transposed. Matrix4 Transpose() const { #ifdef ATOMIC_SSE @@ -621,12 +631,22 @@ class ATOMIC_API Matrix4 /// Return decomposition to translation, rotation and scale. void Decompose(Vector3& translation, Quaternion& rotation, Vector3& scale) const; + /// Return inverse. Matrix4 Inverse() const; - /// Return float data + /// Return float data. const float* Data() const { return &m00_; } + /// Return matrix element. + float Element(unsigned i, unsigned j) const { return Data()[i * 4 + j]; } + + /// Return matrix row. + Vector4 Row(unsigned i) const { return Vector4(Element(i, 0), Element(i, 1), Element(i, 2), Element(i, 3)); } + + /// Return matrix column. + Vector4 Column(unsigned j) const { return Vector4(Element(0, j), Element(1, j), Element(2, j), Element(3, j)); } + /// Return as string. String ToString() const; @@ -691,7 +711,7 @@ class ATOMIC_API Matrix4 static const Matrix4 IDENTITY; }; -/// Multiply a 4x4 matrix with a scalar +/// Multiply a 4x4 matrix with a scalar. inline Matrix4 operator *(float lhs, const Matrix4& rhs) { return rhs * lhs; } } diff --git a/Source/Atomic/Math/Quaternion.cpp b/Source/Atomic/Math/Quaternion.cpp index 938bd835ff..b8fcf01f50 100644 --- a/Source/Atomic/Math/Quaternion.cpp +++ b/Source/Atomic/Math/Quaternion.cpp @@ -221,6 +221,16 @@ float Quaternion::RollAngle() const return EulerAngles().z_; } +Vector3 Quaternion::Axis() const +{ + return Vector3(x_, y_, z_) / sqrt(1 - w_ * w_); +} + +float Quaternion::Angle() const +{ + return 2 * Acos(w_); +} + Matrix3 Quaternion::RotationMatrix() const { return Matrix3( diff --git a/Source/Atomic/Math/Quaternion.h b/Source/Atomic/Math/Quaternion.h index 1db8a0d6d1..894c87e01c 100644 --- a/Source/Atomic/Math/Quaternion.h +++ b/Source/Atomic/Math/Quaternion.h @@ -431,6 +431,10 @@ class ATOMIC_API Quaternion float PitchAngle() const; /// Return roll angle in degrees. float RollAngle() const; + /// Return rotation axis. + Vector3 Axis() const; + /// Return rotation angle. + float Angle() const; /// Return the rotation matrix that corresponds to this quaternion. Matrix3 RotationMatrix() const; /// Spherical interpolation with another quaternion. diff --git a/Source/Atomic/Math/Vector3.h b/Source/Atomic/Math/Vector3.h index 6e776b9d11..eabd4772f8 100644 --- a/Source/Atomic/Math/Vector3.h +++ b/Source/Atomic/Math/Vector3.h @@ -23,6 +23,7 @@ #pragma once #include "../Math/Vector2.h" +#include "../Math/MathDefs.h" namespace Atomic { @@ -356,6 +357,9 @@ class ATOMIC_API Vector3 /// Project vector onto axis. float ProjectOntoAxis(const Vector3& axis) const { return DotProduct(axis.Normalized()); } + /// Make vector orthogonal to the axis. + Vector3 Orthogonalize(const Vector3& axis) const { return axis.CrossProduct(*this).CrossProduct(axis).Normalized(); } + /// Calculate cross product. Vector3 CrossProduct(const Vector3& rhs) const { @@ -415,6 +419,17 @@ class ATOMIC_API Vector3 /// Return as string. String ToString() const; + /// Return hash value for HashSet & HashMap. + unsigned ToHash() const + { + unsigned hash = 37; + hash = 37 * hash + FloatToRawIntBits(x_); + hash = 37 * hash + FloatToRawIntBits(y_); + hash = 37 * hash + FloatToRawIntBits(z_); + + return hash; + } + /// X coordinate. float x_; /// Y coordinate. diff --git a/Source/Atomic/Navigation/DynamicNavigationMesh.cpp b/Source/Atomic/Navigation/DynamicNavigationMesh.cpp index f69b0ab45b..df438ad307 100644 --- a/Source/Atomic/Navigation/DynamicNavigationMesh.cpp +++ b/Source/Atomic/Navigation/DynamicNavigationMesh.cpp @@ -77,7 +77,7 @@ struct TileCompressor : public dtTileCacheCompressor virtual dtStatus compress(const unsigned char* buffer, const int bufferSize, unsigned char* compressed, const int /*maxCompressedSize*/, int* compressedSize) { - *compressedSize = LZ4_compress((const char*)buffer, (char*)compressed, bufferSize); + *compressedSize = LZ4_compress_default((const char*)buffer, (char*)compressed, bufferSize, LZ4_compressBound(bufferSize)); return DT_SUCCESS; } diff --git a/Source/Atomic/Physics/PhysicsWorld.cpp b/Source/Atomic/Physics/PhysicsWorld.cpp index 4e16354e86..f1761bf65f 100644 --- a/Source/Atomic/Physics/PhysicsWorld.cpp +++ b/Source/Atomic/Physics/PhysicsWorld.cpp @@ -34,6 +34,7 @@ #include "../Physics/PhysicsEvents.h" #include "../Physics/PhysicsUtils.h" #include "../Physics/PhysicsWorld.h" +#include "../Physics/RaycastVehicle.h" #include "../Physics/RigidBody.h" #include "../Scene/Scene.h" #include "../Scene/SceneEvents.h" @@ -151,6 +152,7 @@ PhysicsWorld::PhysicsWorld(Context* context) : world_->setDebugDrawer(this); world_->setInternalTickCallback(InternalPreTickCallback, static_cast(this), true); world_->setInternalTickCallback(InternalTickCallback, static_cast(this), false); + world_->setSynchronizeAllMotionStates(true); } @@ -646,15 +648,15 @@ void PhysicsWorld::GetRigidBodies(PODVector& result, const BoundingB void PhysicsWorld::GetRigidBodies(PODVector& result, const RigidBody* body) { ATOMIC_PROFILE(PhysicsBodyQuery); - + result.Clear(); - + if (!body || !body->GetBody()) return; PhysicsQueryCallback callback(result, body->GetCollisionMask()); world_->contactTest(body->GetBody(), callback); - + // Remove the body itself from the returned list for (unsigned i = 0; i < result.Size(); i++) { @@ -1081,6 +1083,7 @@ void RegisterPhysicsLibrary(Context* context) RigidBody::RegisterObject(context); Constraint::RegisterObject(context); PhysicsWorld::RegisterObject(context); + RaycastVehicle::RegisterObject(context); } } diff --git a/Source/Atomic/Physics/RaycastVehicle.cpp b/Source/Atomic/Physics/RaycastVehicle.cpp new file mode 100644 index 0000000000..d2b51b5515 --- /dev/null +++ b/Source/Atomic/Physics/RaycastVehicle.cpp @@ -0,0 +1,744 @@ +// +// Copyright (c) 2008-2017 the Urho3D project. +// +// 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. +// + +#include "../Core/Context.h" +#include "../Physics/PhysicsUtils.h" +#include "../Physics/RigidBody.h" +#include "../Physics/PhysicsWorld.h" +#include "../Scene/Scene.h" +#include "../IO/Log.h" +#include "../Physics/RaycastVehicle.h" + +#include +#include + +namespace Atomic +{ + +struct RaycastVehicleData +{ + RaycastVehicleData() + { + vehicleRayCaster_ = 0; + vehicle_ = 0; + added_ = false; + } + + ~RaycastVehicleData() + { + if (vehicleRayCaster_) + { + delete vehicleRayCaster_; + } + vehicleRayCaster_ = 0; + if (vehicle_) + { + if (physWorld_ && added_) + { + btDynamicsWorld* pbtDynWorld = physWorld_->GetWorld(); + if (pbtDynWorld) + pbtDynWorld->removeAction(vehicle_); + added_ = false; + } + delete vehicle_; + } + vehicle_ = 0; + } + + btRaycastVehicle* Get() + { + return vehicle_; + } + + void Init(Scene* scene, RigidBody* body, bool enabled) + { + int rightIndex = 0; + int upIndex = 1; + int forwardIndex = 2; + PhysicsWorld* pPhysWorld = scene->GetComponent(); + btDynamicsWorld* pbtDynWorld = pPhysWorld->GetWorld(); + if (!pbtDynWorld) + return; + + // Delete old vehicle & action first + if (vehicleRayCaster_) + delete vehicleRayCaster_; + if (vehicle_) + { + if (added_) + pbtDynWorld->removeAction(vehicle_); + delete vehicle_; + } + + vehicleRayCaster_ = new btDefaultVehicleRaycaster(pbtDynWorld); + btRigidBody* bthullBody = body->GetBody(); + vehicle_ = new btRaycastVehicle(tuning_, bthullBody, vehicleRayCaster_); + if (enabled) + { + pbtDynWorld->addAction(vehicle_); + added_ = true; + } + + vehicle_->setCoordinateSystem(rightIndex, upIndex, forwardIndex); + physWorld_ = pPhysWorld; + } + + void SetEnabled(bool enabled) + { + if (!physWorld_ || !vehicle_) + return; + btDynamicsWorld* pbtDynWorld = physWorld_->GetWorld(); + if (!pbtDynWorld) + return; + + if (enabled && !added_) + { + pbtDynWorld->addAction(vehicle_); + added_ = true; + } + else if (!enabled && added_) + { + pbtDynWorld->removeAction(vehicle_); + added_ = false; + } + } + + WeakPtr physWorld_; + btVehicleRaycaster* vehicleRayCaster_; + btRaycastVehicle* vehicle_; + btRaycastVehicle::btVehicleTuning tuning_; + bool added_; +}; + +RaycastVehicle::RaycastVehicle(Context* context) : + LogicComponent(context) +{ + // fixed update() for inputs and post update() to sync wheels for rendering + SetUpdateEventMask(USE_FIXEDUPDATE | USE_FIXEDPOSTUPDATE | USE_POSTUPDATE); + vehicleData_ = new RaycastVehicleData(); + wheelNodes_.Clear(); + activate_ = false; + inAirRPM_ = 0.0f; + maxSideSlipSpeed_ = 4.0f; +} + +RaycastVehicle::~RaycastVehicle() +{ + delete vehicleData_; + wheelNodes_.Clear(); +} + +const char* wheelElementNames[] = +{ + "Number of wheels", + " Wheel node id", + " Wheel direction", + " Wheel axle", + " Wheel rest length", + " Wheel radius", + " Wheel is front wheel", + " Steering", + " Connection point vector", + " Original rotation", + " Cumulative skid info", + " Side skip speed", + " Grounded", + " Contact position", + " Contact normal", + " Suspension stiffness", + " Damping relaxation", + " Damping compression", + " Friction slip", + " Roll influence", + " Engine force", + " Brake", + 0 +}; + +void RaycastVehicle::RegisterObject(Context* context) +{ + context->RegisterFactory(); + ATOMIC_MIXED_ACCESSOR_VARIANT_VECTOR_STRUCTURE_ATTRIBUTE("Wheel data", GetWheelDataAttr, SetWheelDataAttr, + VariantVector, Variant::emptyVariantVector, + wheelElementNames, AM_DEFAULT); + ATOMIC_ATTRIBUTE("Maximum side slip threshold", float, maxSideSlipSpeed_, 4.0f, AM_DEFAULT); + ATOMIC_ATTRIBUTE("RPM for wheel motors in air (0=calculate)", float, inAirRPM_, 0.0f, AM_DEFAULT); +} + +void RaycastVehicle::OnSetEnabled() +{ + if (vehicleData_) + vehicleData_->SetEnabled(IsEnabledEffective()); +} + +void RaycastVehicle::ApplyAttributes() +{ + int index = 0; + hullBody_ = node_->GetOrCreateComponent(); + Scene* scene = GetScene(); + vehicleData_->Init(scene, hullBody_, IsEnabledEffective()); + VariantVector& value = loadedWheelData_; + int numObjects = value[index++].GetInt(); + int wheelIndex = 0; + origRotation_.Clear(); + skidInfoCumulative_.Clear(); + wheelSideSlipSpeed_.Clear(); + + for (int i = 0; i < numObjects; i++) + { + int node_id = value[index++].GetInt(); + Vector3 direction = value[index++].GetVector3(); + Vector3 axle = value[index++].GetVector3(); + float restLength = value[index++].GetFloat(); + float radius = value[index++].GetFloat(); + bool isFrontWheel = value[index++].GetBool(); + float steering = value[index++].GetFloat(); + Vector3 connectionPoint = value[index++].GetVector3(); + Quaternion origRotation = value[index++].GetQuaternion(); + float skidInfoC = value[index++].GetFloat(); + float sideSlipSpeed = value[index++].GetFloat(); + + bool isContact = value[index++].GetBool(); + Vector3 contactPosition = value[index++].GetVector3(); + Vector3 contactNormal = value[index++].GetVector3(); + float suspensionStiffness = value[index++].GetFloat(); + float dampingRelaxation = value[index++].GetFloat(); + float dampingCompression = value[index++].GetFloat(); + float frictionSlip = value[index++].GetFloat(); + float rollInfluence = value[index++].GetFloat(); + float engineForce = value[index++].GetFloat(); + float brake = value[index++].GetFloat(); + float skidInfo = value[index++].GetFloat(); + Node* wheelNode = GetScene()->GetNode(node_id); + if (!wheelNode) + { + ATOMIC_LOGERROR("RaycastVehicle: Incorrect node id = " + String(node_id) + " index: " + String(index)); + continue; + } + btRaycastVehicle* vehicle = vehicleData_->Get(); + int id = GetNumWheels(); + btVector3 connectionPointCS0(connectionPoint.x_, connectionPoint.y_, connectionPoint.z_); + btVector3 wheelDirectionCS0(direction.x_, direction.y_, direction.z_); + btVector3 wheelAxleCS(axle.x_, axle.y_, axle.z_); + btWheelInfo& wheel = vehicle->addWheel(connectionPointCS0, + wheelDirectionCS0, + wheelAxleCS, + restLength, + radius, + vehicleData_->tuning_, + isFrontWheel); + wheelNodes_.Push(wheelNode); + origRotation_.Push(origRotation); + skidInfoCumulative_.Push(skidInfoC); + wheelSideSlipSpeed_.Push(sideSlipSpeed); + SetSteeringValue(wheelIndex, steering); + wheel.m_raycastInfo.m_isInContact = isContact; + wheel.m_raycastInfo.m_contactNormalWS = btVector3(contactNormal.x_, contactNormal.y_, contactNormal.z_); + wheel.m_raycastInfo.m_contactPointWS = btVector3(contactPosition.x_, contactPosition.y_, contactPosition.z_); + wheel.m_suspensionStiffness = suspensionStiffness; + wheel.m_wheelsDampingRelaxation = dampingRelaxation; + wheel.m_wheelsDampingCompression = dampingCompression; + wheel.m_frictionSlip = frictionSlip; + wheel.m_rollInfluence = rollInfluence; + wheel.m_engineForce = engineForce; + wheel.m_brake = brake; + wheel.m_skidInfo = skidInfo; + wheelIndex++; + } + ATOMIC_LOGDEBUG("maxSideSlipSpeed_ value: " + String(maxSideSlipSpeed_)); + ATOMIC_LOGDEBUG("loaded items: " + String(index)); + ATOMIC_LOGDEBUG("loaded wheels: " + String(GetNumWheels())); +} + +void RaycastVehicle::Init() +{ + hullBody_ = node_->GetOrCreateComponent(); + Scene* scene = GetScene(); + vehicleData_->Init(scene, hullBody_, IsEnabledEffective()); +} + +void RaycastVehicle::FixedUpdate(float timeStep) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + for (int i = 0; i < GetNumWheels(); i++) + { + btWheelInfo whInfo = vehicle->getWheelInfo(i); + if (whInfo.m_engineForce != 0.0f || whInfo.m_steering != 0.0f) + { + hullBody_->Activate(); + break; + } + } +} + +void RaycastVehicle::PostUpdate(float timeStep) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + for (int i = 0; i < GetNumWheels(); i++) + { + vehicle->updateWheelTransform(i, true); + btTransform transform = vehicle->getWheelTransformWS(i); + Vector3 origin = ToVector3(transform.getOrigin()); + Quaternion qRot = ToQuaternion(transform.getRotation()); + Node* pWheel = wheelNodes_[i]; + pWheel->SetWorldPosition(origin); + pWheel->SetWorldRotation(qRot * origRotation_[i]); + } +} + +void RaycastVehicle::FixedPostUpdate(float timeStep) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + Vector3 velocity = hullBody_->GetLinearVelocity(); + for (int i = 0; i < GetNumWheels(); i++) + { + btWheelInfo& whInfo = vehicle->getWheelInfo(i); + if (!WheelIsGrounded(i) && GetEngineForce(i) != 0.0f) + { + float delta; + if (inAirRPM_ != 0.0f) + { + delta = inAirRPM_ * timeStep / 60.0f; + } + else + { + delta = 8.0f * GetEngineForce(i) * timeStep / (hullBody_->GetMass() * GetWheelRadius(i)); + } + if (Abs(whInfo.m_deltaRotation) < Abs(delta)) + { + whInfo.m_rotation += delta - whInfo.m_deltaRotation; + whInfo.m_deltaRotation = delta; + } + if (skidInfoCumulative_[i] > 0.05f) + { + skidInfoCumulative_[i] -= 0.002; + } + } + else + { + skidInfoCumulative_[i] = GetWheelSkidInfo(i); + } + wheelSideSlipSpeed_[i] = Abs(ToVector3(whInfo.m_raycastInfo.m_wheelAxleWS).DotProduct(velocity)); + if (wheelSideSlipSpeed_[i] > maxSideSlipSpeed_) + { + skidInfoCumulative_[i] = Clamp(skidInfoCumulative_[i], 0.0f, 0.89f); + } + } +} + +void RaycastVehicle::SetMaxSideSlipSpeed(float speed) +{ + maxSideSlipSpeed_ = speed; +} + +float RaycastVehicle::GetMaxSideSlipSpeed() const +{ + return maxSideSlipSpeed_; +} + +void RaycastVehicle::SetWheelSkidInfoCumulative(int wheel, float skid) +{ + skidInfoCumulative_[wheel] = skid; +} + +float RaycastVehicle::GetWheelSkidInfoCumulative(int wheel) const +{ + return skidInfoCumulative_[wheel]; +} + +void RaycastVehicle::AddWheel(Node* wheelNode, + Vector3 wheelDirection, Vector3 wheelAxle, + float restLength, float wheelRadius, + bool frontWheel) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + int id = GetNumWheels(); + Vector3 connectionPoint = wheelNode->GetWorldPosition() - node_->GetWorldPosition(); + btVector3 connectionPointCS0(connectionPoint.x_, connectionPoint.y_, connectionPoint.z_); + btVector3 wheelDirectionCS0(wheelDirection.x_, wheelDirection.y_, wheelDirection.z_); + btVector3 wheelAxleCS(wheelAxle.x_, wheelAxle.y_, wheelAxle.z_); + btWheelInfo& wheel = vehicle->addWheel(connectionPointCS0, + wheelDirectionCS0, + wheelAxleCS, + restLength, + wheelRadius, + vehicleData_->tuning_, + frontWheel); + + wheelNodes_.Push(wheelNode); + origRotation_.Push(wheelNode->GetWorldRotation()); + skidInfoCumulative_.Push(1.0f); + wheelSideSlipSpeed_.Push(0.0f); + wheel.m_raycastInfo.m_isInContact = false; +} + +void RaycastVehicle::ResetSuspension() +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + vehicle->resetSuspension(); +} + +void RaycastVehicle::UpdateWheelTransform(int wheel, bool interpolated) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + vehicle->updateWheelTransform(wheel, interpolated); +} + +Vector3 RaycastVehicle::GetWheelPosition(int wheel) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btTransform transform = vehicle->getWheelTransformWS(wheel); + Vector3 origin = ToVector3(transform.getOrigin()); + return origin; +} + +Quaternion RaycastVehicle::GetWheelRotation(int wheel) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btTransform transform = vehicle->getWheelTransformWS(wheel); + Quaternion rotation = ToQuaternion(transform.getRotation()); + return rotation; +} + +Vector3 RaycastVehicle::GetWheelConnectionPoint(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return ToVector3(whInfo.m_chassisConnectionPointCS); +} + +void RaycastVehicle::SetSteeringValue(int wheel, float steeringValue) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + vehicle->setSteeringValue(steeringValue, wheel); +} + +float RaycastVehicle::GetSteeringValue(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_steering; +} + +void RaycastVehicle::SetWheelSuspensionStiffness(int wheel, float stiffness) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_suspensionStiffness = stiffness; +} + +float RaycastVehicle::GetWheelSuspensionStiffness(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_suspensionStiffness; +} + +void RaycastVehicle::SetWheelDampingRelaxation(int wheel, float damping) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_wheelsDampingRelaxation = damping; +} + +float RaycastVehicle::GetWheelDampingRelaxation(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_wheelsDampingRelaxation; +} + +void RaycastVehicle::SetWheelDampingCompression(int wheel, float compression) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_wheelsDampingCompression = compression; +} + +float RaycastVehicle::GetWheelDampingCompression(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_wheelsDampingCompression; +} + +void RaycastVehicle::SetWheelFrictionSlip(int wheel, float slip) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_frictionSlip = slip; +} + +float RaycastVehicle::GetWheelFrictionSlip(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_frictionSlip; +} + +void RaycastVehicle::SetWheelRollInfluence(int wheel, float rollInfluence) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_rollInfluence = rollInfluence; +} + +Vector3 RaycastVehicle::GetContactPosition(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return ToVector3(whInfo.m_raycastInfo.m_contactPointWS); +} + +Vector3 RaycastVehicle::GetContactNormal(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return ToVector3(whInfo.m_raycastInfo.m_contactNormalWS); +} + +float RaycastVehicle::GetWheelSideSlipSpeed(int wheel) const +{ + return wheelSideSlipSpeed_[wheel]; +} + +float RaycastVehicle::GetWheelRollInfluence(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_rollInfluence; +} + +void RaycastVehicle::SetWheelRadius(int wheel, float wheelRadius) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_wheelsRadius = wheelRadius; +} + +float RaycastVehicle::GetWheelRadius(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_wheelsRadius; +} + +void RaycastVehicle::SetEngineForce(int wheel, float force) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + vehicle->applyEngineForce(force, wheel); +} + +float RaycastVehicle::GetEngineForce(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_engineForce; +} + +void RaycastVehicle::SetBrake(int wheel, float force) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + vehicle->setBrake(force, wheel); +} + +float RaycastVehicle::GetBrake(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_brake; +} + +int RaycastVehicle::GetNumWheels() const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + return vehicle->getNumWheels(); +} + +Node* RaycastVehicle::GetWheelNode(int wheel) const +{ + return wheelNodes_[wheel]; +} + +void RaycastVehicle::SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_maxSuspensionTravelCm = maxSuspensionTravel; +} + +float RaycastVehicle::GetMaxSuspensionTravel(int wheel) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_maxSuspensionTravelCm; +} + +void RaycastVehicle::SetWheelDirection(int wheel, Vector3 direction) +{ + btVector3 dir(direction.x_, direction.y_, direction.z_); + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_wheelDirectionCS = dir; +} + +Vector3 RaycastVehicle::GetWheelDirection(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return ToVector3(whInfo.m_wheelDirectionCS); +} + +void RaycastVehicle::SetWheelAxle(int wheel, Vector3 axle) +{ + btVector3 ax(axle.x_, axle.y_, axle.z_); + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_wheelAxleCS = ax; +} + +Vector3 RaycastVehicle::GetWheelAxle(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return ToVector3(whInfo.m_wheelAxleCS); +} + +void RaycastVehicle::SetWheelRestLength(int wheel, float length) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_suspensionRestLength1 = length; +} + +float RaycastVehicle::GetWheelRestLength(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_suspensionRestLength1; +} + +void RaycastVehicle::SetWheelSkidInfo(int wheel, float factor) +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + whInfo.m_skidInfo = factor; +} + +float RaycastVehicle::GetWheelSkidInfo(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_skidInfo; +} + +bool RaycastVehicle::IsFrontWheel(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo& whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_bIsFrontWheel; +} + +bool RaycastVehicle::WheelIsGrounded(int wheel) const +{ + btRaycastVehicle* vehicle = vehicleData_->Get(); + btWheelInfo whInfo = vehicle->getWheelInfo(wheel); + return whInfo.m_raycastInfo.m_isInContact; +} + +void RaycastVehicle::SetInAirRPM(float rpm) +{ + inAirRPM_ = rpm; +} + +float RaycastVehicle::GetInAirRPM() const +{ + return inAirRPM_; +} + +void RaycastVehicle::ResetWheels() +{ + ResetSuspension(); + for (int i = 0; i < GetNumWheels(); i++) + { + UpdateWheelTransform(i, true); + Vector3 origin = GetWheelPosition(i); + Node* wheelNode = GetWheelNode(i); + wheelNode->SetWorldPosition(origin); + } +} + +VariantVector RaycastVehicle::GetWheelDataAttr() const +{ + VariantVector ret; + ret.Reserve(GetNumWheels() * 22 + 1); + ret.Push(GetNumWheels()); + for (int i = 0; i < GetNumWheels(); i++) + { + Node* wNode = GetWheelNode(i); + int node_id = wNode->GetID(); + ATOMIC_LOGDEBUG("RaycastVehicle: Saving node id = " + String(node_id)); + ret.Push(node_id); + ret.Push(GetWheelDirection(i)); + ret.Push(GetWheelAxle(i)); + ret.Push(GetWheelRestLength(i)); + ret.Push(GetWheelRadius(i)); + ret.Push(IsFrontWheel(i)); + ret.Push(GetSteeringValue(i)); + ret.Push(GetWheelConnectionPoint(i)); + ret.Push(origRotation_[i]); + ret.Push(GetWheelSkidInfoCumulative(i)); + ret.Push(GetWheelSideSlipSpeed(i)); + ret.Push(WheelIsGrounded(i)); + ret.Push(GetContactPosition(i)); + ret.Push(GetContactNormal(i)); // 14 + ret.Push(GetWheelSuspensionStiffness(i)); + ret.Push(GetWheelDampingRelaxation(i)); + ret.Push(GetWheelDampingCompression(i)); + ret.Push(GetWheelFrictionSlip(i)); + ret.Push(GetWheelRollInfluence(i)); + ret.Push(GetEngineForce(i)); + ret.Push(GetBrake(i)); + ret.Push(GetWheelSkidInfo(i)); + } + ATOMIC_LOGDEBUG("RaycastVehicle: saved items: " + String(ret.Size())); + ATOMIC_LOGDEBUG("maxSideSlipSpeed_ value save: " + String(maxSideSlipSpeed_)); + return ret; +} + +void RaycastVehicle::SetWheelDataAttr(const VariantVector& value) +{ + if (!vehicleData_) + { + ATOMIC_LOGERROR("RaycastVehicle: vehicleData doesn't exist"); + return; + } + if (value.Size() < 2) + { + ATOMIC_LOGERROR("RaycastVehicle: Incorrect vehicleData"); + return; + } + + loadedWheelData_ = value; +} + +} // namespace Urho3D diff --git a/Source/Atomic/Physics/RaycastVehicle.h b/Source/Atomic/Physics/RaycastVehicle.h new file mode 100644 index 0000000000..ba6b2554b6 --- /dev/null +++ b/Source/Atomic/Physics/RaycastVehicle.h @@ -0,0 +1,187 @@ +// +// Copyright (c) 2008-2017 the Urho3D project. +// +// 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. +// + +#pragma once + +#include "../Scene/LogicComponent.h" +#include "../Physics/PhysicsUtils.h" +#include "../Physics/RigidBody.h" + +namespace Atomic +{ + +struct RaycastVehicleData; + +class ATOMIC_API RaycastVehicle : public LogicComponent +{ + ATOMIC_OBJECT(RaycastVehicle, LogicComponent) + +public: + /// Construct. + RaycastVehicle(Atomic::Context* context); + /// Destruct. + ~RaycastVehicle(); + + /// Register object factory and attributes. + static void RegisterObject(Context* context); + + /// Handle enabled/disabled state change. + virtual void OnSetEnabled(); + + /// Perform post-load after deserialization. Acquire the components from the scene nodes. + virtual void ApplyAttributes(); + + /// Add a wheel. All parameters are relative to RigidBody / node. + void AddWheel(Node* wheelNode, Vector3 wheelDirection, Vector3 wheelAxle, float restLength, float wheelRadius, bool frontWheel); + /// Reset all suspension. + void ResetSuspension(void); + /// Update transform for particular wheel. + void UpdateWheelTransform(int wheel, bool interpolated); + /// Set steering value of particular wheel. + void SetSteeringValue(int wheel, float steeringValue); + /// Set suspension stiffness for particular wheel. + void SetWheelSuspensionStiffness(int wheel, float stiffness); + /// Set wheel damping relaxation. + void SetWheelDampingRelaxation(int wheel, float damping); + /// Set wheel damping compression. + void SetWheelDampingCompression(int wheel, float compression); + /// Set wheel friction slip. + void SetWheelFrictionSlip(int wheel, float slip); + /// Set wheel roll influence. + void SetWheelRollInfluence(int wheel, float rollInfluence); + /// Set engine force for the wheel. + void SetEngineForce(int wheel, float force); + /// Set hand brake (wheel rotation blocking force.) + void SetBrake(int wheel, float force); + /// Set wheel radius. + void SetWheelRadius(int wheel, float wheelRadius); + /// Sets node initial positions. + void ResetWheels(); + /// Set sliding factor 0 <= x <= 1. The less the value, more sliding. + void SetWheelSkidInfo(int wheel, float factor); + /// True if wheel touches ground (raycast hits something.) + bool WheelIsGrounded(int wheel) const; + /// Set maximum suspension travel value. + void SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel); + /// Set wheel direction vector. + void SetWheelDirection(int wheel, Vector3 direction); + /// Set wheel axle vector. + void SetWheelAxle(int wheel, Vector3 axle); + /// Set side speed which is considered sliding. + void SetMaxSideSlipSpeed(float speed); + /// Set cumulative skid info. + void SetWheelSkidInfoCumulative(int wheel, float skid); + /// Set revolution per minute value for when wheel doesn't touch ground. If set to 0 (or not set), calculated from engine force (probably not what you want). + void SetInAirRPM(float rpm); + /// Init the vehicle component after creation + void Init(); + /// Perform fixed step pre-update. + void FixedUpdate(float timeStep); + /// Perform fixed step post-update. + void FixedPostUpdate(float timeStep); + /// Perform variable step post-update. + void PostUpdate(float timeStep); + + /// Get wheel position relative to RigidBody. + Vector3 GetWheelPosition(int wheel); + /// Get wheel rotation relative to RigidBody. + Quaternion GetWheelRotation(int wheel); + /// Get wheel connection point relative to RigidBody. + Vector3 GetWheelConnectionPoint(int wheel) const; + /// Get number of attached wheels. + int GetNumWheels() const; + /// Get node of the wheel. + Node* GetWheelNode(int wheel) const; + /// Get steering value of particular wheel. + float GetSteeringValue(int wheel) const; + /// Get suspension stiffness for particular wheel. + float GetWheelSuspensionStiffness(int wheel) const; + /// Get wheel damping relaxation. + float GetWheelDampingRelaxation(int wheel) const; + /// Get wheel damping compression. + float GetWheelDampingCompression(int wheel) const; + /// Get wheel friction slip. + float GetWheelFrictionSlip(int wheel) const; + /// Get wheel roll influence. + float GetWheelRollInfluence(int wheel) const; + /// Get engine force for the wheel. + float GetEngineForce(int wheel) const; + /// Get hand brake value. + float GetBrake(int wheel) const; + /// Get wheel radius. + float GetWheelRadius(int wheel) const; + /// Get wheel rest length. + void SetWheelRestLength(int wheel, float length); + /// Get wheel rest length. + float GetWheelRestLength(int wheel) const; + /// Get maximum suspension travel value. + float GetMaxSuspensionTravel(int wheel); + /// Get wheel axle vector. + Vector3 GetWheelAxle(int wheel) const; + /// Get wheel slide speed. + float GetWheelSideSlipSpeed(int wheel) const; + /// Get side speed which is considered sliding. + float GetMaxSideSlipSpeed() const; + /// Sliding factor 0 <= x <= 1. + float GetWheelSkidInfo(int wheel) const; + /// Get wheel direction vector. + Vector3 GetWheelDirection(int wheel) const; + /// Get cumulative skid info. + float GetWheelSkidInfoCumulative(int wheel) const; + /// True if front wheel, otherwise false. + bool IsFrontWheel(int wheel) const; + /// Get wheel contact position. + Vector3 GetContactPosition(int wheel) const; + /// Get contact normal. + Vector3 GetContactNormal(int wheel) const; + /// Get revolution per minute value for when wheel doesn't touch ground. + float GetInAirRPM() const; + + /// Get wheel data attribute for serialization. + VariantVector GetWheelDataAttr() const; + /// Set wheel data attribute during loading. + void SetWheelDataAttr(const VariantVector& value); + +private: + /// If the RigidBody should be activated. + bool activate_; + /// Hull RigidBody + WeakPtr hullBody_; + /// Opaque Bullet data hidden from public + RaycastVehicleData* vehicleData_; + /// Nodes of all wheels + Vector wheelNodes_; + /// All wheels original rotations. These are applied in addition to wheel rotations by btRaycastVehicle + Vector origRotation_; + /// Revolutions per minute value for in-air motor wheels. FIXME: set this one per wheel + float inAirRPM_; + /// Per-wheel extra settings. + Vector skidInfoCumulative_; + /// Wheel side movement speed. + Vector wheelSideSlipSpeed_; + /// Side slip speed threshold. + float maxSideSlipSpeed_; + /// Loaded data temporarily wait here for ApplyAttributes to come pick them up. + VariantVector loadedWheelData_; +}; + +} diff --git a/Source/Atomic/Resource/JSONFile.cpp b/Source/Atomic/Resource/JSONFile.cpp index c97cfc6c28..0fae00f8ac 100644 --- a/Source/Atomic/Resource/JSONFile.cpp +++ b/Source/Atomic/Resource/JSONFile.cpp @@ -128,7 +128,7 @@ bool JSONFile::BeginLoad(Deserializer& source) buffer[dataSize] = '\0'; rapidjson::Document document; - if (document.Parse<0>(buffer).HasParseError()) + if (document.Parse(buffer).HasParseError()) { ATOMIC_LOGERROR("Could not parse JSON data from " + source.GetName()); return false; @@ -202,7 +202,7 @@ static void ToRapidjsonValue(rapidjson::Value& rapidjsonValue, const JSONValue& const char* name = i->first_.CString(); rapidjson::Value value; ToRapidjsonValue(value, i->second_, allocator); - rapidjsonValue.AddMember(name, value, allocator); + rapidjsonValue.AddMember(StringRef(name), value, allocator); } } break; diff --git a/Source/Atomic/Resource/JSONValue.cpp b/Source/Atomic/Resource/JSONValue.cpp index 28dfe2550c..53c40fdeac 100644 --- a/Source/Atomic/Resource/JSONValue.cpp +++ b/Source/Atomic/Resource/JSONValue.cpp @@ -322,7 +322,7 @@ JSONObjectIterator JSONValue::End() // Convert to object type. SetType(JSON_OBJECT); - return objectValue_->Begin(); + return objectValue_->End(); } ConstJSONObjectIterator JSONValue::End() const @@ -581,7 +581,8 @@ VariantMap JSONValue::GetVariantMap() const for (ConstJSONObjectIterator i = Begin(); i != End(); ++i) { - StringHash key(ToUInt(i->first_)); + /// \todo Ideally this should allow any strings, but for now the convention is that the keys need to be hexadecimal StringHashes + StringHash key(ToUInt(i->first_, 16)); Variant variant = i->second_.GetVariant(); variantMap[key] = variant; } diff --git a/Source/Atomic/Resource/Resource.cpp b/Source/Atomic/Resource/Resource.cpp index 1e0d0dda04..f741250c4d 100644 --- a/Source/Atomic/Resource/Resource.cpp +++ b/Source/Atomic/Resource/Resource.cpp @@ -26,6 +26,7 @@ #include "../IO/File.h" #include "../IO/Log.h" #include "../Resource/Resource.h" +#include "../Resource/XMLElement.h" namespace Atomic { @@ -120,4 +121,66 @@ unsigned Resource::GetUseTimer() return useTimer_.GetMSec(false); } +void ResourceWithMetadata::AddMetadata(const String& name, const Variant& value) +{ + bool exists; + metadata_.Insert(MakePair(StringHash(name), value), exists); + if (!exists) + metadataKeys_.Push(name); +} + +void ResourceWithMetadata::RemoveMetadata(const String& name) +{ + metadata_.Erase(name); + metadataKeys_.Remove(name); +} + +void ResourceWithMetadata::RemoveAllMetadata() +{ + metadata_.Clear(); + metadataKeys_.Clear(); +} + +const Variant& ResourceWithMetadata::GetMetadata(const String& name) const +{ + const Variant* value = metadata_[name]; + return value ? *value : Variant::EMPTY; +} + +bool ResourceWithMetadata::HasMetadata() const +{ + return !metadata_.Empty(); +} + +void ResourceWithMetadata::LoadMetadataFromXML(const XMLElement& source) +{ + for (XMLElement elem = source.GetChild("metadata"); elem; elem = elem.GetNext("metadata")) + AddMetadata(elem.GetAttribute("name"), elem.GetVariant()); +} + +void ResourceWithMetadata::LoadMetadataFromJSON(const JSONArray& array) +{ + for (unsigned i = 0; i < array.Size(); i++) + { + const JSONValue& value = array.At(i); + AddMetadata(value.Get("name").GetString(), value.GetVariant()); + } +} + +void ResourceWithMetadata::SaveMetadataToXML(XMLElement& destination) const +{ + for (unsigned i = 0; i < metadataKeys_.Size(); ++i) + { + XMLElement elem = destination.CreateChild("metadata"); + elem.SetString("name", metadataKeys_[i]); + elem.SetVariant(GetMetadata(metadataKeys_[i])); + } +} + +void ResourceWithMetadata::CopyMetadata(const ResourceWithMetadata& source) +{ + metadata_ = source.metadata_; + metadataKeys_ = source.metadataKeys_; +} + } diff --git a/Source/Atomic/Resource/Resource.h b/Source/Atomic/Resource/Resource.h index a1cec9c41f..1b2ff35345 100644 --- a/Source/Atomic/Resource/Resource.h +++ b/Source/Atomic/Resource/Resource.h @@ -24,12 +24,14 @@ #include "../Core/Object.h" #include "../Core/Timer.h" +#include "../Resource/JSONValue.h" namespace Atomic { class Deserializer; class Serializer; +class XMLElement; /// Asynchronous loading state of a resource. enum AsyncLoadState @@ -106,6 +108,43 @@ class ATOMIC_API Resource : public Object AsyncLoadState asyncLoadState_; }; +/// Base class for resources that support arbitrary metadata stored. Metadata serialization shall be implemented in derived classes. +class ATOMIC_API ResourceWithMetadata : public Resource +{ + ATOMIC_OBJECT(ResourceWithMetadata, Resource); + +public: + /// Construct. + ResourceWithMetadata(Context* context) : Resource(context) {} + + /// Add new metadata variable or overwrite old value. + void AddMetadata(const String& name, const Variant& value); + /// Remove metadata variable. + void RemoveMetadata(const String& name); + /// Remove all metadata variables. + void RemoveAllMetadata(); + /// Return metadata variable. + const Variant& GetMetadata(const String& name) const; + /// Return whether the resource has metadata. + bool HasMetadata() const; + +protected: + /// Load metadata from children of XML element. + void LoadMetadataFromXML(const XMLElement& source); + /// Load metadata from JSON array.float + void LoadMetadataFromJSON(const JSONArray& array); + /// Save as children of XML element. + void SaveMetadataToXML(XMLElement& destination) const; + /// Copy metadata from another resource. + void CopyMetadata(const ResourceWithMetadata& source); + +private: + /// Animation metadata variables. + VariantMap metadata_; + /// Animation metadata keys. + StringVector metadataKeys_; +}; + inline const String& GetResourceName(Resource* resource) { return resource ? resource->GetName() : String::EMPTY; diff --git a/Source/Atomic/Resource/ResourceCache.cpp b/Source/Atomic/Resource/ResourceCache.cpp index 2b5209c5a3..7bea452824 100644 --- a/Source/Atomic/Resource/ResourceCache.cpp +++ b/Source/Atomic/Resource/ResourceCache.cpp @@ -907,7 +907,7 @@ String ResourceCache::SanitateResourceName(const String& nameIn) const if (resourceDirs_.Size()) { String namePath = GetPath(name); - String exePath = fileSystem->GetProgramDir(); + String exePath = fileSystem->GetProgramDir().Replaced("/./", "/"); for (unsigned i = 0; i < resourceDirs_.Size(); ++i) { String relativeResourcePath = resourceDirs_[i]; diff --git a/Source/Atomic/Resource/ResourceCache.h b/Source/Atomic/Resource/ResourceCache.h index 9a7e624be6..92ffdac18d 100644 --- a/Source/Atomic/Resource/ResourceCache.h +++ b/Source/Atomic/Resource/ResourceCache.h @@ -115,7 +115,7 @@ class ATOMIC_API ResourceCache : public Object bool AddPackageFile(PackageFile* package, unsigned priority = PRIORITY_LAST); /// Add a package file for loading resources from by name. Optional priority parameter which will control search order. bool AddPackageFile(const String& fileName, unsigned priority = PRIORITY_LAST); - /// Add a manually created resource. Must be uniquely named. + /// Add a manually created resource. Must be uniquely named within its type. bool AddManualResource(Resource* resource); /// Remove a resource load directory. void RemoveResourceDir(const String& pathName); @@ -193,7 +193,7 @@ class ATOMIC_API ResourceCache : public Object template bool BackgroundLoadResource(const String& name, bool sendEventOnFailure = true, Resource* caller = 0); /// Template version of returning loaded resources of a specific type. template void GetResources(PODVector& result) const; - /// Return whether a file exists by name. + /// Return whether a file exists in the resource directories or package files. Does not check manually added in-memory resources. bool Exists(const String& name) const; /// Return memory budget for a resource type. unsigned long long GetMemoryBudget(StringHash type) const; diff --git a/Source/Atomic/Scene/Node.cpp b/Source/Atomic/Scene/Node.cpp index 5de9a9c0e1..dea52fbfbb 100644 --- a/Source/Atomic/Scene/Node.cpp +++ b/Source/Atomic/Scene/Node.cpp @@ -1188,6 +1188,14 @@ void Node::RemoveListener(Component* component) } } +Vector3 Node::GetSignedWorldScale() const +{ + if (dirty_) + UpdateWorldTransform(); + + return worldTransform_.SignedScale(worldRotation_.RotationMatrix()); +} + Vector3 Node::LocalToWorld(const Vector3& position) const { return GetWorldTransform() * position; @@ -1933,7 +1941,7 @@ Animatable* Node::FindAttributeAnimationTarget(const String& name, String& outNa { if (names[i].Front() != '#') break; - + String name = names[i].Substring(1, names[i].Length() - 1); char s = name.Front(); if (s >= '0' && s <= '9') @@ -1945,7 +1953,7 @@ Animatable* Node::FindAttributeAnimationTarget(const String& name, String& outNa { node = node->GetChild(name, true); } - + if (!node) { ATOMIC_LOGERROR("Could not find node by name " + name); @@ -2114,9 +2122,12 @@ void Node::UpdateWorldTransform() const void Node::RemoveChild(Vector >::Iterator i) { - // Send change event. Do not send when already being destroyed - Node* child = *i; + // Keep a shared pointer to the child about to be removed, to make sure the erase from container completes first. Otherwise + // it would be possible that other child nodes get removed as part of the node's components' cleanup, causing a re-entrant + // erase and a crash + SharedPtr child(*i); + // Send change event. Do not send when this node is already being destroyed if (Refs() > 0 && scene_) { using namespace NodeRemoved; diff --git a/Source/Atomic/Scene/Node.h b/Source/Atomic/Scene/Node.h index dfd04ad88a..780485e24e 100644 --- a/Source/Atomic/Scene/Node.h +++ b/Source/Atomic/Scene/Node.h @@ -464,6 +464,9 @@ class ATOMIC_API Node : public Animatable return worldTransform_.Scale(); } + /// Return signed scale in world space. Utilized for Urho2D physics. + Vector3 GetSignedWorldScale() const; + /// Return scale in world space (for Atomic2D). Vector2 GetWorldScale2D() const { diff --git a/Source/Atomic/Scene/ValueAnimationInfo.h b/Source/Atomic/Scene/ValueAnimationInfo.h index 339fd26fbf..3db816dea3 100644 --- a/Source/Atomic/Scene/ValueAnimationInfo.h +++ b/Source/Atomic/Scene/ValueAnimationInfo.h @@ -22,7 +22,9 @@ #pragma once +#include "../Container/Ptr.h" #include "../Container/RefCounted.h" +#include "../Container/Vector.h" #include "../Scene/AnimationDefs.h" namespace Atomic @@ -30,6 +32,7 @@ namespace Atomic class Object; class ValueAnimation; +class Variant; struct VAnimEventFrame; /// Base class for a value animation instance, which includes animation runtime information and updates the target object's value automatically. diff --git a/Source/AtomicNET/NETNative/CMakeLists.txt b/Source/AtomicNET/NETNative/CMakeLists.txt index dc2e158d29..1b3a03f964 100644 --- a/Source/AtomicNET/NETNative/CMakeLists.txt +++ b/Source/AtomicNET/NETNative/CMakeLists.txt @@ -32,7 +32,7 @@ target_include_directories(AtomicNETNative PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) if (APPLE) if (NOT IOS) - target_link_libraries( AtomicNETNative "-stdlib=libc++ -framework AudioToolbox -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreVideo -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security") + target_link_libraries( AtomicNETNative "-stdlib=libc++ -framework AudioToolbox -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreVideo -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security -framework SystemConfiguration") else() set_target_properties(AtomicNETNative PROPERTIES FRAMEWORK TRUE diff --git a/Source/ThirdParty/Bullet/AUTHORS.txt b/Source/ThirdParty/Bullet/AUTHORS.txt index 8e5b831e7e..556e6f641c 100644 --- a/Source/ThirdParty/Bullet/AUTHORS.txt +++ b/Source/ThirdParty/Bullet/AUTHORS.txt @@ -35,5 +35,6 @@ Marten Svanfeldt Pierre Terdiman Steven Thompson Tamas Umenhoffer +Yunfei Bai If your name is missing, please send an email to erwin.coumans@gmail.com or file an issue at http://github.com/bulletphysics/bullet3 diff --git a/Source/ThirdParty/Bullet/README.md b/Source/ThirdParty/Bullet/README.md index 2f254a0f4a..5c654bd04f 100644 --- a/Source/ThirdParty/Bullet/README.md +++ b/Source/ThirdParty/Bullet/README.md @@ -2,18 +2,20 @@ [![Travis Build Status](https://api.travis-ci.org/bulletphysics/bullet3.png?branch=master)](https://travis-ci.org/bulletphysics/bullet3) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/6sly9uxajr6xsstq)](https://ci.appveyor.com/project/erwincoumans/bullet3) -# Bullet 2.x including experimental Bullet 3 OpenCL. +# Bullet Physics SDK -This is the official repository of Bullet 2.x, moved from http://bullet.googlecode.com -It includes the optional work-in-progress Bullet 3 GPU pipeline. +This is the official C++ source code repository of the Bullet Physics SDK: real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc. -The Bullet 2 API will stay default and up-to-date while slowly moving to Bullet 3. -The steps towards Bullet 3 are in a nutshell: +New in Bullet 2.85: pybullet Python bindings, improved support for robotics and VR + +The Bullet 2 API will stay default and up-to-date while slowly moving to a new API. +The steps towards a new API is in a nutshell: 1. The old Bullet2 demos are being merged into the examples/ExampleBrowser -2. A new Bullet 3 API is created -3. All Bullet2 functionality is added to Bullet 3. -4. The OpenCL examples in the ExampleBrowser can be enabled using --enable_experimental_opencl +2. A new physics-engine agnostic C-API is created, see examples/SharedMemory/PhysicsClientC_API.h +3. Python bindings in pybullet are on top of this C-API, see examples/pybullet +4. A Virtual Reality sandbox using openvr for HTC Vive and Oculus Rift is available +5. The OpenCL examples in the ExampleBrowser can be enabled using --enable_experimental_opencl You can still use svn or svn externals using the github git repository: use svn co https://github.com/bulletphysics/bullet3/trunk @@ -27,14 +29,14 @@ Some optional demos require OpenGL 2 or OpenGL 3, there are some non-graphical d https://docs.google.com/document/d/1u9vyzPtrVoVhYqQOGNWUgjRbfwfCdIts_NzmvgiJ144/edit -## Requirements for Bullet 3 +## Requirements for experimental OpenCL GPGPU support -The entire collision detection and rigid body dynamics is executed on the GPU. +The entire collision detection and rigid body dynamics can be executed on the GPU. A high-end desktop GPU, such as an AMD Radeon 7970 or NVIDIA GTX 680 or better. We succesfully tested the software under Windows, Linux and Mac OSX. The software currently doesn't work on OpenCL CPU devices. It might run -on a laptop GPU but performance is likely not very good. Note that +on a laptop GPU but performance will not likely be very good. Note that often an OpenCL drivers fails to compile a kernel. Some unit tests exist to track down the issue, but more work is required to cover all OpenCL kernels. @@ -47,7 +49,19 @@ All source code files are licensed under the permissive zlib license **Windows** -Click on build3/vs2010.bat and open build3/vs2010/0MySolution.sln +Click on build_visual_studio.bat and open build3/vs2010/0MySolution.sln + +**Windows Virtual Reality sandbox for HTC Vive and Oculus Rift** + +Click on build_visual_studio_vr_pybullet_double.bat and open build3/vs2010/0MySolution.sln +Edit this batch file to choose where Python include/lib directories are located. +Build and run the App_SharedMemoryPhysics_VR project, preferably in Release/optimized build. +You can connect from Python pybullet to the sandbox using: + +``` +import pybullet as p +p.connect(p.SHARED_MEMORY) +``` **Linux and Mac OSX gnu make** @@ -55,7 +69,7 @@ In a terminal type: cd build3 -Dependend on your system (Linux 32bit, 64bit or Mac OSX) use one of the following lines +Depending on your system (Linux 32bit, 64bit or Mac OSX) use one of the following lines ./premake4_linux gmake ./premake4_linux64 gmake @@ -80,15 +94,14 @@ You can just run it though a terminal/command prompt, or by clicking it. ``` [--start_demo_name="Demo Name"] Start with a selected demo -[--enable_experimental_opencl] Enable some experimental OpenCL examples [--mp4=moviename.mp4] Create a mp4 movie of the window, requires ffmpeg installed [--mouse_move_multiplier=0.400000] Set the mouse move sensitivity [--mouse_wheel_multiplier=0.01] Set the mouse wheel sensitivity -[--background_color_red= 0.9] Set the red component for background color. Same for green and blue. +[--background_color_red= 0.9] Set the red component for background color. Same for green and blue [--fixed_timestep= 0.0] Use either a real-time delta time (0.0) or a fixed step size (0.016666) ``` -You can use mouse picking to grab objects. When holding the ALT of CONTROL key, you have Maya style camera mouse controls. -Press F1 to create series of screenshot. Hit ESCAPE to exit the demo app. +You can use mouse picking to grab objects. When holding the ALT or CONTROL key, you have Maya style camera mouse controls. +Press F1 to create a series of screenshots. Hit ESCAPE to exit the demo app. -See docs folder for further information. +Check out the docs folder and the Bullet physics forums for further information. diff --git a/Source/ThirdParty/Bullet/VERSION b/Source/ThirdParty/Bullet/VERSION index 660a62cb24..0104e57c4d 100644 --- a/Source/ThirdParty/Bullet/VERSION +++ b/Source/ThirdParty/Bullet/VERSION @@ -1 +1 @@ -2.84 +2.86 diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index cd6e1a8929..58e3524197 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -134,7 +134,7 @@ class btAxisSweep3Internal : public btBroadphaseInterface virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher); void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} @@ -144,7 +144,7 @@ class btAxisSweep3Internal : public btBroadphaseInterface void processAllOverlappingPairs(btOverlapCallback* callback); //Broadphase Interface - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher); virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; @@ -228,16 +228,16 @@ void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinalit #endif //DEBUG_BROADPHASE template -btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher) { (void)shapeType; - BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); + BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher); Handle* handle = getHandle(handleId); if (m_raycastAccelerator) { - btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0); + btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher); handle->m_dbvtProxy = rayProxy; } return handle; @@ -502,7 +502,7 @@ void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) template -BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher) { // quantize the bounds BP_FP_INT_TYPE min[3], max[3]; @@ -520,7 +520,6 @@ BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& pHandle->m_clientObject = pOwner; pHandle->m_collisionFilterGroup = collisionFilterGroup; pHandle->m_collisionFilterMask = collisionFilterMask; - pHandle->m_multiSapParentProxy = multiSapProxy; // compute current limit of edge arrays BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index f1bf00594d..d31b77f468 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -53,7 +53,7 @@ class btBroadphaseInterface public: virtual ~btBroadphaseInterface() {} - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) =0; virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index bb58b82893..adaf083a21 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -101,10 +101,10 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); //Usually the client btCollisionObject or Rigidbody class void* m_clientObject; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; - void* m_multiSapParentProxy; - int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + int m_collisionFilterGroup; + int m_collisionFilterMask; + + int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. btVector3 m_aabbMin; btVector3 m_aabbMax; @@ -115,18 +115,17 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); } //used for memory pools - btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) + btBroadphaseProxy() :m_clientObject(0) { } - btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) + btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) :m_clientObject(userPtr), m_collisionFilterGroup(collisionFilterGroup), m_collisionFilterMask(collisionFilterMask), m_aabbMin(aabbMin), m_aabbMax(aabbMax) { - m_multiSapParentProxy = multiSapParentProxy; } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h index e05e1de27d..1ca1757233 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h @@ -122,6 +122,7 @@ subject to the following restrictions: #error "DBVT_INT0_IMPL undefined" #endif + // // Defaults volumes // @@ -188,6 +189,9 @@ struct btDbvtNode }; }; +typedef btAlignedObjectArray btNodeStack; + + ///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). ///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. ///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. @@ -263,7 +267,6 @@ struct btDbvt btAlignedObjectArray m_stkStack; - mutable btAlignedObjectArray m_rayTestStack; // Methods @@ -325,6 +328,16 @@ struct btDbvt void collideTV( const btDbvtNode* root, const btDbvtVolume& volume, DBVT_IPOLICY) const; + + DBVT_PREFIX + void collideTVNoStackAlloc( const btDbvtNode* root, + const btDbvtVolume& volume, + btNodeStack& stack, + DBVT_IPOLICY) const; + + + + ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc) ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time DBVT_PREFIX @@ -343,6 +356,7 @@ struct btDbvt btScalar lambda_max, const btVector3& aabbMin, const btVector3& aabbMax, + btAlignedObjectArray& stack, DBVT_IPOLICY) const; DBVT_PREFIX @@ -917,39 +931,72 @@ inline void btDbvt::collideTT( const btDbvtNode* root0, } #endif -// DBVT_PREFIX inline void btDbvt::collideTV( const btDbvtNode* root, const btDbvtVolume& vol, DBVT_IPOLICY) const { DBVT_CHECKTYPE - if(root) - { - ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); - btAlignedObjectArray stack; - stack.resize(0); - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(root); - do { - const btDbvtNode* n=stack[stack.size()-1]; - stack.pop_back(); - if(Intersect(n->volume,volume)) + if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + btAlignedObjectArray stack; + stack.resize(0); + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) + { + if(n->isinternal()) { - if(n->isinternal()) - { - stack.push_back(n->childs[0]); - stack.push_back(n->childs[1]); - } - else - { - policy.Process(n); - } + stack.push_back(n->childs[0]); + stack.push_back(n->childs[1]); } - } while(stack.size()>0); - } + else + { + policy.Process(n); + } + } + } while(stack.size()>0); + } } +// +DBVT_PREFIX +inline void btDbvt::collideTVNoStackAlloc( const btDbvtNode* root, + const btDbvtVolume& vol, + btNodeStack& stack, + DBVT_IPOLICY) const +{ + DBVT_CHECKTYPE + if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + stack.resize(0); + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) + { + if(n->isinternal()) + { + stack.push_back(n->childs[0]); + stack.push_back(n->childs[1]); + } + else + { + policy.Process(n); + } + } + } while(stack.size()>0); + } +} + + DBVT_PREFIX inline void btDbvt::rayTestInternal( const btDbvtNode* root, const btVector3& rayFrom, @@ -959,7 +1006,8 @@ inline void btDbvt::rayTestInternal( const btDbvtNode* root, btScalar lambda_max, const btVector3& aabbMin, const btVector3& aabbMax, - DBVT_IPOLICY) const + btAlignedObjectArray& stack, + DBVT_IPOLICY ) const { (void) rayTo; DBVT_CHECKTYPE @@ -969,7 +1017,6 @@ inline void btDbvt::rayTestInternal( const btDbvtNode* root, int depth=1; int treshold=DOUBLE_STACKSIZE-2; - btAlignedObjectArray& stack = m_rayTestStack; stack.resize(DOUBLE_STACKSIZE); stack[0]=root; btVector3 bounds[2]; @@ -1196,23 +1243,32 @@ inline void btDbvt::collideOCL( const btDbvtNode* root, //void * memmove ( void * destination, const void * source, size_t num ); -//#if DBVT_USE_MEMMOVE -// memmove(&stack[j],&stack[j-1],sizeof(int)*(stack.size()-j-1)); -//#else - for(int k=stack.size()-1;k>j;--k) - { +#if DBVT_USE_MEMMOVE + { + int num_items_to_move = stack.size()-1-j; + if(num_items_to_move > 0) + memmove(&stack[j+1],&stack[j],sizeof(int)*num_items_to_move); + } +#else + for(int k=stack.size()-1;k>j;--k) { stack[k]=stack[k-1]; - } -//#endif + } +#endif stack[j]=allocate(ifree,stock,nes[q]); /* Insert 1 */ j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); stack.push_back(0); -//#if DBVT_USE_MEMMOVE -// memmove(&stack[j],&stack[j-1],sizeof(int)*(stack.size()-j-1)); -//#else - for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; -//#endif +#if DBVT_USE_MEMMOVE + { + int num_items_to_move = stack.size()-1-j; + if(num_items_to_move > 0) + memmove(&stack[j+1],&stack[j],sizeof(int)*num_items_to_move); + } +#else + for(int k=stack.size()-1;k>j;--k) { + stack[k]=stack[k-1]; + } +#endif stack[j]=allocate(ifree,stock,nes[1-q]); } else diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp index 75cfac6436..9e4933f796 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -16,6 +16,7 @@ subject to the following restrictions: ///btDbvtBroadphase implementation by Nathanael Presson #include "btDbvtBroadphase.h" +#include "LinearMath/btThreads.h" // // Profiling @@ -142,6 +143,11 @@ btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) { m_stageRoots[i]=0; } +#if BT_THREADSAFE + m_rayTestStacks.resize(BT_MAX_THREAD_COUNT); +#else + m_rayTestStacks.resize(1); +#endif #if DBVT_BP_PROFILE clear(m_profiling); #endif @@ -162,10 +168,9 @@ btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax, int /*shapeType*/, void* userPtr, - short int collisionFilterGroup, - short int collisionFilterMask, - btDispatcher* /*dispatcher*/, - void* /*multiSapProxy*/) + int collisionFilterGroup, + int collisionFilterMask, + btDispatcher* /*dispatcher*/) { btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr, collisionFilterGroup, @@ -227,6 +232,23 @@ struct BroadphaseRayTester : btDbvt::ICollide void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) { BroadphaseRayTester callback(rayCallback); + btAlignedObjectArray* stack = &m_rayTestStacks[0]; +#if BT_THREADSAFE + // for this function to be threadsafe, each thread must have a separate copy + // of this stack. This could be thread-local static to avoid dynamic allocations, + // instead of just a local. + int threadIndex = btGetCurrentThreadIndex(); + btAlignedObjectArray localStack; + if (threadIndex < m_rayTestStacks.size()) + { + // use per-thread preallocated stack if possible to avoid dynamic allocations + stack = &m_rayTestStacks[threadIndex]; + } + else + { + stack = &localStack; + } +#endif m_sets[0].rayTestInternal( m_sets[0].m_root, rayFrom, @@ -236,6 +258,7 @@ void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, rayCallback.m_lambda_max, aabbMin, aabbMax, + *stack, callback); m_sets[1].rayTestInternal( m_sets[1].m_root, @@ -246,6 +269,7 @@ void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, rayCallback.m_lambda_max, aabbMin, aabbMax, + *stack, callback); } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h index 18b64ad0e5..8feb95d51f 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -47,7 +47,7 @@ struct btDbvtProxy : btBroadphaseProxy btDbvtProxy* links[2]; int stage; /* ctor */ - btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : + btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) : btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask) { links[0]=links[1]=0; @@ -87,6 +87,7 @@ struct btDbvtBroadphase : btBroadphaseInterface bool m_releasepaircache; // Release pair cache on delete bool m_deferedcollide; // Defere dynamic/static collision to collide call bool m_needcleanup; // Need to run cleanup? + btAlignedObjectArray< btAlignedObjectArray > m_rayTestStacks; #if DBVT_BP_PROFILE btClock m_clock; struct { @@ -104,7 +105,7 @@ struct btDbvtBroadphase : btBroadphaseInterface void optimize(); /* btBroadphaseInterface Implementation */ - btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher); virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 89c307d14c..7b0f9489af 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -64,6 +64,12 @@ struct btDispatcherInfo btScalar m_convexConservativeDistanceThreshold; }; +enum ebtDispatcherQueryType +{ + BT_CONTACT_POINT_ALGORITHMS = 1, + BT_CLOSEST_POINT_ALGORITHMS = 2 +}; + ///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. ///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). class btDispatcher @@ -73,7 +79,7 @@ class btDispatcher public: virtual ~btDispatcher() ; - virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold=0) = 0; + virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0; virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp deleted file mode 100644 index 81369fe9b5..0000000000 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without 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. -*/ - -#include "btMultiSapBroadphase.h" - -#include "btSimpleBroadphase.h" -#include "LinearMath/btAabbUtil2.h" -#include "btQuantizedBvh.h" - -/// btSapBroadphaseArray m_sapBroadphases; - -/// btOverlappingPairCache* m_overlappingPairs; -extern int gOverlappingPairs; - -/* -class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache -{ -public: - - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) - { - return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); - } -}; - -*/ - -btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) -:m_overlappingPairs(pairCache), -m_optimizedAabbTree(0), -m_ownsPairCache(false), -m_invalidPair(0) -{ - if (!m_overlappingPairs) - { - m_ownsPairCache = true; - void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); - m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); - } - - struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback - { - virtual ~btMultiSapOverlapFilterCallback() - {} - // return true when pairs need collision - virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const - { - btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; - btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; - - bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; - collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); - - return collides; - } - }; - - void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); - m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); - - m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); -// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); -// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); -} - -btMultiSapBroadphase::~btMultiSapBroadphase() -{ - if (m_ownsPairCache) - { - m_overlappingPairs->~btOverlappingPairCache(); - btAlignedFree(m_overlappingPairs); - } -} - - -void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) -{ - m_optimizedAabbTree = new btQuantizedBvh(); - m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); - QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray(); - for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax); - m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); - m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); - int partId = 0; - node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; - nodes.push_back(node); - } - m_optimizedAabbTree->buildInternal(); -} - -btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) -{ - //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested - - void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); - btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); - m_multiSapProxies.push_back(proxy); - - ///this should deal with inserting/removal into child broadphases - setAabb(proxy,aabbMin,aabbMax,dispatcher); - return proxy; -} - -void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) -{ - ///not yet - btAssert(0); - -} - - -void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase) -{ - void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); - btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; - bridgeProxyRef->m_childProxy = childProxy; - bridgeProxyRef->m_childBroadphase = childBroadphase; - parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); -} - - -bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); -bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) -{ -return -amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && -amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && -amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); -} - - - - - - -void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const -{ - btMultiSapProxy* multiProxy = static_cast(proxy); - aabbMin = multiProxy->m_aabbMin; - aabbMax = multiProxy->m_aabbMax; -} - -void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) -{ - for (int i=0;i - -void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) -{ - btMultiSapProxy* multiProxy = static_cast(proxy); - multiProxy->m_aabbMin = aabbMin; - multiProxy->m_aabbMax = aabbMax; - - -// bool fullyContained = false; -// bool alreadyInSimple = false; - - - - - struct MyNodeOverlapCallback : public btNodeOverlapCallback - { - btMultiSapBroadphase* m_multiSap; - btMultiSapProxy* m_multiProxy; - btDispatcher* m_dispatcher; - - MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) - :m_multiSap(multiSap), - m_multiProxy(multiProxy), - m_dispatcher(dispatcher) - { - - } - - virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) - { - btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; - - int containingBroadphaseIndex = -1; - //already found? - for (int i=0;im_bridgeProxies.size();i++) - { - - if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) - { - containingBroadphaseIndex = i; - break; - } - } - if (containingBroadphaseIndex<0) - { - //add it - btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); - m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); - - } - } - }; - - MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); - - - - - if (m_optimizedAabbTree) - m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); - - int i; - - for ( i=0;im_bridgeProxies.size();i++) - { - btVector3 worldAabbMin,worldAabbMax; - multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); - bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); - if (!overlapsBroadphase) - { - //remove it now - btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; - - btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; - bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); - - multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); - multiProxy->m_bridgeProxies.pop_back(); - - } - } - - - /* - - if (1) - { - - //find broadphase that contain this multiProxy - int numChildBroadphases = getBroadphaseArray().size(); - for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax); - bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); - - // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); - int containingBroadphaseIndex = -1; - - //if already contains this - - for (int i=0;im_bridgeProxies.size();i++) - { - if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) - { - containingBroadphaseIndex = i; - } - alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); - } - - if (overlapsBroadphase) - { - if (containingBroadphaseIndex<0) - { - btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); - childProxy->m_multiSapParentProxy = multiProxy; - addToChildBroadphase(multiProxy,childProxy,childBroadphase); - } - } else - { - if (containingBroadphaseIndex>=0) - { - //remove - btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; - - btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; - bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); - - multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); - multiProxy->m_bridgeProxies.pop_back(); - } - } - } - - - ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) - ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) - if (0)//!multiProxy->m_bridgeProxies.size()) - { - ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision - ///this is needed to be able to calculate the aabb overlap - btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); - childProxy->m_multiSapParentProxy = multiProxy; - addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); - } - } - - if (!multiProxy->m_bridgeProxies.size()) - { - ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision - ///this is needed to be able to calculate the aabb overlap - btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); - childProxy->m_multiSapParentProxy = multiProxy; - addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); - } -*/ - - - //update - for ( i=0;im_bridgeProxies.size();i++) - { - btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; - bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); - } - -} -bool stopUpdating=false; - - - -class btMultiSapBroadphasePairSortPredicate -{ - public: - - bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const - { - btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; - btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; - btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; - btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; - - return aProxy0 > bProxy0 || - (aProxy0 == bProxy0 && aProxy1 > bProxy1) || - (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); - } -}; - - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb -void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) -{ - -// m_simpleBroadphase->calculateOverlappingPairs(dispatcher); - - if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) - { - - btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); - - // quicksort(overlappingPairArray,0,overlappingPairArray.size()); - - overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;im_multiSapParentProxy : 0; - btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; - btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; - btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; - - bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); - - previousPair = pair; - - bool needsRemoval = false; - - if (!isDuplicate) - { - bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); - - if (hasOverlap) - { - needsRemoval = false;//callback->processOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - - ///if you don't like to skip the invalid pairs in the array, execute following code: - #define CLEAN_INVALID_PAIRS 1 - #ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); - overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - #endif//CLEAN_INVALID_PAIRS - - //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); - } - - -} - - -bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) -{ - btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; - btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; - - return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, - multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); - -} - - -void btMultiSapBroadphase::printStats() -{ -/* printf("---------------------------------\n"); - - printf("btMultiSapBroadphase.h\n"); - printf("numHandles = %d\n",m_multiSapProxies.size()); - //find broadphase that contain this multiProxy - int numChildBroadphases = getBroadphaseArray().size(); - for (int i=0;iprintStats(); - - } - */ - -} - -void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher) -{ - // not yet -} diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h deleted file mode 100644 index 7bcfe6b132..0000000000 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without 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 BT_MULTI_SAP_BROADPHASE -#define BT_MULTI_SAP_BROADPHASE - -#include "btBroadphaseInterface.h" -#include "LinearMath/btAlignedObjectArray.h" -#include "btOverlappingPairCache.h" - - -class btBroadphaseInterface; -class btSimpleBroadphase; - - -typedef btAlignedObjectArray btSapBroadphaseArray; - -///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead. -///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. -///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. -///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. -///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 -///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 -class btMultiSapBroadphase :public btBroadphaseInterface -{ - btSapBroadphaseArray m_sapBroadphases; - - btSimpleBroadphase* m_simpleBroadphase; - - btOverlappingPairCache* m_overlappingPairs; - - class btQuantizedBvh* m_optimizedAabbTree; - - - bool m_ownsPairCache; - - btOverlapFilterCallback* m_filterCallback; - - int m_invalidPair; - - struct btBridgeProxy - { - btBroadphaseProxy* m_childProxy; - btBroadphaseInterface* m_childBroadphase; - }; - - -public: - - struct btMultiSapProxy : public btBroadphaseProxy - { - - ///array with all the entries that this proxy belongs to - btAlignedObjectArray m_bridgeProxies; - btVector3 m_aabbMin; - btVector3 m_aabbMax; - - int m_shapeType; - -/* void* m_userPtr; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; -*/ - btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) - :btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask), - m_aabbMin(aabbMin), - m_aabbMax(aabbMax), - m_shapeType(shapeType) - { - m_multiSapParentProxy =this; - } - - - }; - -protected: - - - btAlignedObjectArray m_multiSapProxies; - -public: - - btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); - - - btSapBroadphaseArray& getBroadphaseArray() - { - return m_sapBroadphases; - } - - const btSapBroadphaseArray& getBroadphaseArray() const - { - return m_sapBroadphases; - } - - virtual ~btMultiSapBroadphase(); - - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; - - virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); - - void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - virtual btOverlappingPairCache* getOverlappingPairCache() - { - return m_overlappingPairs; - } - virtual const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_overlappingPairs; - } - - ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame - ///will add some transform later - virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const - { - aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); - aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); - } - - void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); - - virtual void printStats(); - - void quicksort (btBroadphasePairArray& a, int lo, int hi); - - ///reset broadphase internal structures, to ensure determinism/reproducability - virtual void resetPool(btDispatcher* dispatcher); - -}; - -#endif //BT_MULTI_SAP_BROADPHASE diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp index ae22dadc73..55ebf06f1e 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -34,7 +34,6 @@ int gFindPairs =0; btHashedOverlappingPairCache::btHashedOverlappingPairCache(): m_overlapFilterCallback(0), - m_blockedForChanges(false), m_ghostPairCallback(0) { int initialAllocatedSize= 2; @@ -373,10 +372,10 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro return userData; } //#include - +#include "LinearMath/btQuickprof.h" void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) { - + BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs"); int i; // printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index eee90e473a..6488bdd648 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -90,11 +90,11 @@ class btOverlappingPairCache : public btOverlappingPairCallback }; /// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com -class btHashedOverlappingPairCache : public btOverlappingPairCache + +ATTRIBUTE_ALIGNED16(class) btHashedOverlappingPairCache : public btOverlappingPairCache { btBroadphasePairArray m_overlappingPairArray; btOverlapFilterCallback* m_overlapFilterCallback; - bool m_blockedForChanges; protected: @@ -104,6 +104,8 @@ class btHashedOverlappingPairCache : public btOverlappingPairCache public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btHashedOverlappingPairCache(); virtual ~btHashedOverlappingPairCache(); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp index 889216df50..93de499988 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @@ -107,6 +107,8 @@ void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btV v = unQuantize(vecIn); m_bvhAabbMin.setMin(v-clampValue); } + aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; { quantize(vecIn,m_bvhAabbMax,true); v = unQuantize(vecIn); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h index 78382da79f..3dd5ac9bb6 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -169,7 +169,7 @@ typedef btAlignedObjectArray BvhSubtreeInfoArray; ///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. -///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. +///It is used by the btBvhTriangleMeshShape as midphase. ///It is recommended to use quantization for better performance and lower memory requirements. ATTRIBUTE_ALIGNED16(class) btQuantizedBvh { diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index 752fcd0fef..f1d5f5476e 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -84,7 +84,7 @@ btSimpleBroadphase::~btSimpleBroadphase() } -btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/) { if (m_numHandles >= m_maxHandles) { @@ -94,7 +94,7 @@ btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); int newHandleIndex = allocHandle(); - btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); return proxy; } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index 7cb3c40a04..d7a18e400a 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -29,8 +29,8 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy btSimpleBroadphaseProxy() {}; - btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) - :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy) + btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask) + :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask) { (void)shapeType; } @@ -127,7 +127,7 @@ class btSimpleBroadphase : public btBroadphaseInterface static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher); virtual void calculateOverlappingPairs(btDispatcher* dispatcher); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index 6340178097..c81af95672 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -100,45 +100,54 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po btScalar radiusWithThreshold = radius + contactBreakingThreshold; btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); - normal.normalize(); - btVector3 p1ToCentre = sphereCenter - vertices[0]; - btScalar distanceFromPlane = p1ToCentre.dot(normal); - if (distanceFromPlane < btScalar(0.)) + btScalar l2 = normal.length2(); + bool hasContact = false; + btVector3 contactPoint; + + if (l2 >= SIMD_EPSILON*SIMD_EPSILON) { - //triangle facing the other way - distanceFromPlane *= btScalar(-1.); - normal *= btScalar(-1.); - } + normal /= btSqrt(l2); + + btVector3 p1ToCentre = sphereCenter - vertices[0]; + btScalar distanceFromPlane = p1ToCentre.dot(normal); - bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold; + if (distanceFromPlane < btScalar(0.)) + { + //triangle facing the other way + distanceFromPlane *= btScalar(-1.); + normal *= btScalar(-1.); + } + + bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold; - // Check for contact / intersection - bool hasContact = false; - btVector3 contactPoint; - if (isInsideContactPlane) { - if (facecontains(sphereCenter,vertices,normal)) { - // Inside the contact wedge - touches a point on the shell plane - hasContact = true; - contactPoint = sphereCenter - normal*distanceFromPlane; - } else { - // Could be inside one of the contact capsules - btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold; - btVector3 nearestOnEdge; - for (int i = 0; i < m_triangle->getNumEdges(); i++) { - - btVector3 pa; - btVector3 pb; - - m_triangle->getEdge(i,pa,pb); - - btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge); - if (distanceSqr < contactCapsuleRadiusSqr) { - // Yep, we're inside a capsule - hasContact = true; - contactPoint = nearestOnEdge; + // Check for contact / intersection + + if (isInsideContactPlane) { + if (facecontains(sphereCenter, vertices, normal)) { + // Inside the contact wedge - touches a point on the shell plane + hasContact = true; + contactPoint = sphereCenter - normal*distanceFromPlane; + } + else { + // Could be inside one of the contact capsules + btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold; + btVector3 nearestOnEdge; + for (int i = 0; i < m_triangle->getNumEdges(); i++) { + + btVector3 pa; + btVector3 pb; + + m_triangle->getEdge(i, pa, pb); + + btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge); + if (distanceSqr < contactCapsuleRadiusSqr) { + // Yep, we're inside a capsule + hasContact = true; + contactPoint = nearestOnEdge; + } + } - } } } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h index 6694984944..35f77d4e65 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -40,6 +40,9 @@ class btCollisionConfiguration virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; + virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0; + + }; #endif //BT_COLLISION_CONFIGURATION diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index 3b6913c0e1..5739a1ef01 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -16,7 +16,7 @@ subject to the following restrictions: #include "btCollisionDispatcher.h" - +#include "LinearMath/btQuickprof.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" @@ -50,8 +50,10 @@ m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESH { for (int j=0;jgetCollisionAlgorithmCreateFunc(i,j); - btAssert(m_doubleDispatch[i][j]); + m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j); + btAssert(m_doubleDispatchContactPoints[i][j]); + m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j); + } } @@ -61,7 +63,12 @@ m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESH void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) { - m_doubleDispatch[proxyType0][proxyType1] = createFunc; + m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc; +} + +void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) +{ + m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc; } btCollisionDispatcher::~btCollisionDispatcher() @@ -84,14 +91,10 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObj btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold()); - void* mem = 0; - - if (m_persistentManifoldPoolAllocator->getFreeCount()) - { - mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); - } else + void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) ); + if (NULL == mem) { - //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert. + //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert. if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0) { mem = btAlignedAlloc(sizeof(btPersistentManifold),16); @@ -142,14 +145,23 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) -btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold) + +btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType) { btCollisionAlgorithmConstructionInfo ci; ci.m_dispatcher1 = this; ci.m_manifold = sharedManifold; - btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap); + btCollisionAlgorithm* algo = 0; + if (algoType == BT_CONTACT_POINT_ALGORITHMS) + { + algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap); + } + else + { + algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap); + } return algo; } @@ -228,7 +240,6 @@ class btCollisionPairCallback : public btOverlapCallback virtual bool processOverlap(btBroadphasePair& pair) { (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); - return false; } }; @@ -249,7 +260,6 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa - //by default, Bullet will use this near callback void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { @@ -265,7 +275,7 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, //dispatcher will keep algorithms persistent in the collision pair if (!collisionPair.m_algorithm) { - collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap); + collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap,0, BT_CONTACT_POINT_ALGORITHMS); } if (collisionPair.m_algorithm) @@ -293,13 +303,13 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) { - if (m_collisionAlgorithmPoolAllocator->getFreeCount()) - { - return m_collisionAlgorithmPoolAllocator->allocate(size); - } - - //warn user for overflow? - return btAlignedAlloc(static_cast(size), 16); + void* mem = m_collisionAlgorithmPoolAllocator->allocate( size ); + if (NULL == mem) + { + //warn user for overflow? + return btAlignedAlloc(static_cast(size), 16); + } + return mem; } void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index 92696ee542..b97ee3c1ba 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -57,7 +57,9 @@ class btCollisionDispatcher : public btDispatcher btPoolAllocator* m_persistentManifoldPoolAllocator; - btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; + btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; + + btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; btCollisionConfiguration* m_collisionConfiguration; @@ -84,6 +86,8 @@ class btCollisionDispatcher : public btDispatcher ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); + void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc); + int getNumManifolds() const { return int( m_manifoldsPtr.size()); @@ -115,7 +119,7 @@ class btCollisionDispatcher : public btDispatcher virtual void clearManifold(btPersistentManifold* manifold); - btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold = 0); + btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType); virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp index 395df3a550..fdecac162b 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -28,13 +28,18 @@ btCollisionObject::btCollisionObject() m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), m_islandTag1(-1), m_companionId(-1), + m_worldArrayIndex(-1), m_activationState1(1), m_deactivationTime(btScalar(0.)), m_friction(btScalar(0.5)), m_restitution(btScalar(0.)), m_rollingFriction(0.0f), + m_spinningFriction(0.f), + m_contactDamping(.1), + m_contactStiffness(1e4), m_internalType(CO_COLLISION_OBJECT), m_userObjectPointer(0), + m_userIndex2(-1), m_userIndex(-1), m_hitFraction(btScalar(1.)), m_ccdSweptSphereRadius(btScalar(0.)), @@ -91,6 +96,8 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali dataOut->m_deactivationTime = m_deactivationTime; dataOut->m_friction = m_friction; dataOut->m_rollingFriction = m_rollingFriction; + dataOut->m_contactDamping = m_contactDamping; + dataOut->m_contactStiffness = m_contactStiffness; dataOut->m_restitution = m_restitution; dataOut->m_internalType = m_internalType; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h index c68402418f..0cae210000 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -79,13 +79,19 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject int m_islandTag1; int m_companionId; + int m_worldArrayIndex; // index of object in world's collisionObjects array mutable int m_activationState1; mutable btScalar m_deactivationTime; btScalar m_friction; btScalar m_restitution; - btScalar m_rollingFriction; + btScalar m_rollingFriction;//torsional friction orthogonal to contact normal (useful to stop spheres rolling forever) + btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping) + btScalar m_contactDamping; + btScalar m_contactStiffness; + + ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc. ///do not assign your own m_internalType unless you write a new dynamics object class. @@ -93,8 +99,10 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer - void* m_userObjectPointer; - + void* m_userObjectPointer; + + int m_userIndex2; + int m_userIndex; ///time of impact calculation @@ -114,6 +122,7 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject ///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation. int m_updateRevision; + btVector3 m_customDebugColorRGB; public: @@ -127,7 +136,9 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) CF_CHARACTER_OBJECT = 16, CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing - CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing + CF_DISABLE_SPU_COLLISION_PROCESSING = 64,//disable parallel/SPU processing + CF_HAS_CONTACT_STIFFNESS_DAMPING = 128, + CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256, }; enum CollisionObjectTypes @@ -316,8 +327,40 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject { return m_rollingFriction; } - - + void setSpinningFriction(btScalar frict) + { + m_updateRevision++; + m_spinningFriction = frict; + } + btScalar getSpinningFriction() const + { + return m_spinningFriction; + } + void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping) + { + m_updateRevision++; + m_contactStiffness = stiffness; + m_contactDamping = damping; + + m_collisionFlags |=CF_HAS_CONTACT_STIFFNESS_DAMPING; + + //avoid divisions by zero... + if (m_contactStiffness< SIMD_EPSILON) + { + m_contactStiffness = SIMD_EPSILON; + } + } + + btScalar getContactStiffness() const + { + return m_contactStiffness; + } + + btScalar getContactDamping() const + { + return m_contactDamping; + } + ///reserved for Bullet internal usage int getInternalType() const { @@ -415,7 +458,18 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject m_companionId = id; } - SIMD_FORCE_INLINE btScalar getHitFraction() const + SIMD_FORCE_INLINE int getWorldArrayIndex() const + { + return m_worldArrayIndex; + } + + // only should be called by CollisionWorld + void setWorldArrayIndex(int ix) + { + m_worldArrayIndex = ix; + } + + SIMD_FORCE_INLINE btScalar getHitFraction() const { return m_hitFraction; } @@ -476,6 +530,12 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject { return m_userIndex; } + + int getUserIndex2() const + { + return m_userIndex2; + } + ///users can point to their objects, userPointer is not used by Bullet void setUserPointer(void* userPointer) { @@ -487,12 +547,37 @@ ATTRIBUTE_ALIGNED16(class) btCollisionObject { m_userIndex = index; } + + void setUserIndex2(int index) + { + m_userIndex2 = index; + } int getUpdateRevisionInternal() const { return m_updateRevision; } + void setCustomDebugColor(const btVector3& colorRGB) + { + m_customDebugColorRGB = colorRGB; + m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR; + } + + void removeCustomDebugColor() + { + m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR; + } + + bool getCustomDebugColor(btVector3& colorRGB) const + { + bool hasCustomColor = (0!=(m_collisionFlags&CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR)); + if (hasCustomColor) + { + colorRGB = m_customDebugColorRGB; + } + return hasCustomColor; + } inline bool checkCollideWith(const btCollisionObject* co) const { @@ -528,6 +613,8 @@ struct btCollisionObjectDoubleData double m_deactivationTime; double m_friction; double m_rollingFriction; + double m_contactDamping; + double m_contactStiffness; double m_restitution; double m_hitFraction; double m_ccdSweptSphereRadius; @@ -561,7 +648,8 @@ struct btCollisionObjectFloatData float m_deactivationTime; float m_friction; float m_rollingFriction; - + float m_contactDamping; + float m_contactStiffness; float m_restitution; float m_hitFraction; float m_ccdSweptSphereRadius; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 3d9a382ccb..19d86a34a1 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -110,14 +110,16 @@ btCollisionWorld::~btCollisionWorld() -void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask) { btAssert(collisionObject); //check that the object isn't already added btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size()); + btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world + collisionObject->setWorldArrayIndex(m_collisionObjects.size()); m_collisionObjects.push_back(collisionObject); //calculate new AABB @@ -135,8 +137,7 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho collisionObject, collisionFilterGroup, collisionFilterMask, - m_dispatcher1,0 - )) ; + m_dispatcher1)) ; @@ -197,6 +198,7 @@ void btCollisionWorld::updateAabbs() for ( int i=0;igetWorldArrayIndex() == i); //only update aabb of active objects if (m_forceUpdateAllAabbs || colObj->isActive()) @@ -255,9 +257,25 @@ void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) } - //swapremove - m_collisionObjects.remove(collisionObject); - + int iObj = collisionObject->getWorldArrayIndex(); +// btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously? + if (iObj >= 0 && iObj < m_collisionObjects.size()) + { + btAssert(collisionObject == m_collisionObjects[iObj]); + m_collisionObjects.swap(iObj, m_collisionObjects.size()-1); + m_collisionObjects.pop_back(); + if (iObj < m_collisionObjects.size()) + { + m_collisionObjects[iObj]->setWorldArrayIndex(iObj); + } + } + else + { + // slow linear search + //swapremove + m_collisionObjects.remove(collisionObject); + } + collisionObject->setWorldArrayIndex(-1); } @@ -792,23 +810,50 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, } } } else { - ///@todo : use AABB tree or other BVH acceleration structure! if (collisionShape->isCompound()) { - BT_PROFILE("convexSweepCompound"); - const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) + struct btCompoundLeafCallback : btDbvt::ICollide { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - - struct LocalInfoAdder : public ConvexResultCallback { - ConvexResultCallback* m_userCallback; + btCompoundLeafCallback( + const btCollisionObjectWrapper* colObjWrap, + const btConvexShape* castShape, + const btTransform& convexFromTrans, + const btTransform& convexToTrans, + btScalar allowedPenetration, + const btCompoundShape* compoundShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback) + : + m_colObjWrap(colObjWrap), + m_castShape(castShape), + m_convexFromTrans(convexFromTrans), + m_convexToTrans(convexToTrans), + m_allowedPenetration(allowedPenetration), + m_compoundShape(compoundShape), + m_colObjWorldTransform(colObjWorldTransform), + m_resultCallback(resultCallback) { + } + + const btCollisionObjectWrapper* m_colObjWrap; + const btConvexShape* m_castShape; + const btTransform& m_convexFromTrans; + const btTransform& m_convexToTrans; + btScalar m_allowedPenetration; + const btCompoundShape* m_compoundShape; + const btTransform& m_colObjWorldTransform; + ConvexResultCallback& m_resultCallback; + + public: + + void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape) + { + btTransform childWorldTrans = m_colObjWorldTransform * childTrans; + + struct LocalInfoAdder : public ConvexResultCallback { + ConvexResultCallback* m_userCallback; int m_i; - LocalInfoAdder (int i, ConvexResultCallback *user) + LocalInfoAdder(int i, ConvexResultCallback *user) : m_userCallback(user), m_i(i) { m_closestHitFraction = m_userCallback->m_closestHitFraction; @@ -817,27 +862,66 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, { return m_userCallback->needsCollision(p); } - virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult& r, bool b) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = -1; - shapeInfo.m_triangleIndex = m_i; - if (r.m_localShapeInfo == NULL) - r.m_localShapeInfo = &shapeInfo; - const btScalar result = m_userCallback->addSingleResult(r, b); - m_closestHitFraction = m_userCallback->m_closestHitFraction; - return result; - - } - }; + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; - LocalInfoAdder my_cb(i, &resultCallback); - - btCollisionObjectWrapper tmpObj(colObjWrap,childCollisionShape,colObjWrap->getCollisionObject(),childWorldTrans,-1,i); + } + }; - objectQuerySingleInternal(castShape, convexFromTrans,convexToTrans, - &tmpObj,my_cb, allowedPenetration); - + LocalInfoAdder my_cb(index, &m_resultCallback); + + btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index); + + objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration); + } + + void Process(const btDbvtNode* leaf) + { + // Processing leaf node + int index = leaf->dataAsInt; + + btTransform childTrans = m_compoundShape->getChildTransform(index); + const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); + + ProcessChild(index, childTrans, childCollisionShape); + } + }; + + BT_PROFILE("convexSweepCompound"); + const btCompoundShape* compoundShape = static_cast(collisionShape); + + btVector3 fromLocalAabbMin, fromLocalAabbMax; + btVector3 toLocalAabbMin, toLocalAabbMax; + + castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax); + castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax); + + fromLocalAabbMin.setMin(toLocalAabbMin); + fromLocalAabbMax.setMax(toLocalAabbMax); + + btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans, + allowedPenetration, compoundShape, colObjWorldTransform, resultCallback); + + const btDbvt* tree = compoundShape->getDynamicAabbTree(); + if (tree) { + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); + tree->collideTV(tree->m_root, bounds, callback); + } else { + int i; + for (i=0;igetNumChildShapes();i++) + { + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childTrans = compoundShape->getChildTransform(i); + callback.ProcessChild(i, childTrans, childCollisionShape); + } } } } @@ -1148,7 +1232,7 @@ struct btSingleContactCallback : public btBroadphaseAabbCallback btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1); btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1); - btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1); + btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1,0, BT_CLOSEST_POINT_ALGORITHMS); if (algorithm) { btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback); @@ -1184,10 +1268,11 @@ void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionOb btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1); btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1); - btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB); + btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB, 0, BT_CLOSEST_POINT_ALGORITHMS); if (algorithm) { btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback); + contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold; //discrete collision detection query algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult); @@ -1500,6 +1585,8 @@ void btCollisionWorld::debugDrawWorld() } }; + colObj->getCustomDebugColor(color); + debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); } if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index b3fffdecd9..eede2b28ca 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -27,7 +27,7 @@ subject to the following restrictions: * @section install_sec Installation * * @subsection step1 Step 1: Download - * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list + * You can download the Bullet Physics Library from the github repository: https://github.com/bulletphysics/bullet3/releases * * @subsection step2 Step 2: Building * Bullet has multiple build systems, including premake, cmake and autotools. Premake and cmake support all platforms. @@ -205,8 +205,8 @@ class btCollisionWorld { btScalar m_closestHitFraction; const btCollisionObject* m_collisionObject; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; + int m_collisionFilterGroup; + int m_collisionFilterMask; //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke. unsigned int m_flags; @@ -340,8 +340,8 @@ class btCollisionWorld struct ConvexResultCallback { btScalar m_closestHitFraction; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; + int m_collisionFilterGroup; + int m_collisionFilterMask; ConvexResultCallback() :m_closestHitFraction(btScalar(1.)), @@ -410,12 +410,14 @@ class btCollisionWorld ///ContactResultCallback is used to report contact points struct ContactResultCallback { - short int m_collisionFilterGroup; - short int m_collisionFilterMask; - + int m_collisionFilterGroup; + int m_collisionFilterMask; + btScalar m_closestDistanceThreshold; + ContactResultCallback() :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), - m_collisionFilterMask(btBroadphaseProxy::AllFilter) + m_collisionFilterMask(btBroadphaseProxy::AllFilter), + m_closestDistanceThreshold(0) { } @@ -481,7 +483,7 @@ class btCollisionWorld const btCollisionObjectWrapper* colObjWrap, ConvexResultCallback& resultCallback, btScalar allowedPenetration); - virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter); btCollisionObjectArray& getCollisionObjectArray() { diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp index 36dd043509..f2b0837808 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp @@ -579,13 +579,13 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData; btCompoundShape* compoundShape = createCompoundShape(); - btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0]; + //btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0]; btAlignedObjectArray childShapes; for (int i=0;im_numChildShapes;i++) { - btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i]; + //btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i]; btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 09b692c42b..1ab4b37ee3 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -67,7 +67,13 @@ void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionO const btCollisionShape* childShape = compoundShape->getChildShape(i); btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully) - m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold); + m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS); + + + btAlignedObjectArray m_childCollisionAlgorithmsContact; + btAlignedObjectArray m_childCollisionAlgorithmsClosestPoints; + + } } } @@ -130,8 +136,14 @@ struct btCompoundLeafCallback : btDbvt::ICollide btTransform newChildWorldTrans = orgTrans*childTrans ; //perform an AABB check first - btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + btVector3 aabbMin0,aabbMax0; childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + + btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold); + aabbMin0 -= extendAabb; + aabbMax0 += extendAabb; + + btVector3 aabbMin1, aabbMax1; m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1); if (gCompoundChildShapePairCallback) @@ -144,12 +156,22 @@ struct btCompoundLeafCallback : btDbvt::ICollide { btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index); + + btCollisionAlgorithm* algo = 0; - - //the contactpoint is still projected back using the original inverted worldtrans - if (!m_childCollisionAlgorithms[index]) - m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap,m_otherObjWrap,m_sharedManifold); - + if (m_resultOut->m_closestPointDistanceThreshold > 0) + { + algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS); + } + else + { + //the contactpoint is still projected back using the original inverted worldtrans + if (!m_childCollisionAlgorithms[index]) + { + m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS); + } + algo = m_childCollisionAlgorithms[index]; + } const btCollisionObjectWrapper* tmpWrap = 0; @@ -166,8 +188,7 @@ struct btCompoundLeafCallback : btDbvt::ICollide m_resultOut->setShapeIdentifiersB(-1,index); } - - m_childCollisionAlgorithms[index]->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut); + algo->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut); #if 0 if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) @@ -250,7 +271,7 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm { int i; - btManifoldArray manifoldArray; + manifoldArray.resize(0); for (i=0;igetWorldTransform().inverse() * otherObjWrap->getWorldTransform(); otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); + btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold); + localAabbMin -= extraExtends; + localAabbMax += extraExtends; const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); //process all children, that overlap with the given AABB bounds - tree->collideTV(tree->m_root,bounds,callback); + tree->collideTVNoStackAlloc(tree->m_root,bounds,stack2,callback); } else { @@ -297,7 +321,7 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap //iterate over all children, perform an AABB check inside ProcessChildShape int numChildren = m_childCollisionAlgorithms.size(); int i; - btManifoldArray manifoldArray; + manifoldArray.resize(0); const btCollisionShape* childShape = 0; btTransform orgTrans; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 7d792c18d3..d2086fbc02 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -26,6 +26,7 @@ class btDispatcher; #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" #include "LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" class btDispatcher; class btCollisionObject; @@ -36,6 +37,9 @@ extern btShapePairCallback gCompoundChildShapePairCallback; /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm { + btNodeStack stack2; + btManifoldArray manifoldArray; + protected: btAlignedObjectArray m_childCollisionAlgorithms; bool m_isSwapped; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp index 1d64d84b87..d4a1aa78e4 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp @@ -15,6 +15,7 @@ subject to the following restrictions: */ #include "btCompoundCompoundCollisionAlgorithm.h" +#include "LinearMath/btQuickprof.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/BroadphaseCollision/btDbvt.h" @@ -23,6 +24,8 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btManifoldResult.h" #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" +//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT +#define USE_LOCAL_STACK 1 btShapePairCallback gCompoundCompoundChildShapePairCallback = 0; @@ -124,6 +127,7 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1) { + BT_PROFILE("btCompoundCompoundLeafCallback::Process"); m_numOverlapPairs++; @@ -159,6 +163,11 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0); childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1); + btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold); + + aabbMin0 -= thresholdVec; + aabbMax0 += thresholdVec; + if (gCompoundCompoundChildShapePairCallback) { if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1)) @@ -174,17 +183,24 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1); btCollisionAlgorithm* colAlgo = 0; - - if (pair) + if (m_resultOut->m_closestPointDistanceThreshold > 0) { - colAlgo = (btCollisionAlgorithm*)pair->m_userPointer; - - } else + colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS); + } + else { - colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0,&compoundWrap1,m_sharedManifold); - pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0,childIndex1); - btAssert(pair); - pair->m_userPointer = colAlgo; + if (pair) + { + colAlgo = (btCollisionAlgorithm*)pair->m_userPointer; + + } + else + { + colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS); + pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1); + btAssert(pair); + pair->m_userPointer = colAlgo; + } } btAssert(colAlgo); @@ -215,10 +231,12 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a, - const btDbvtAabbMm& b, const btTransform& xform) + const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold) { btVector3 newmin,newmax; btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax); + newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold); + newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold); btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax); return Intersect(a,newb); } @@ -227,7 +245,7 @@ static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a, static inline void MycollideTT( const btDbvtNode* root0, const btDbvtNode* root1, const btTransform& xform, - btCompoundCompoundLeafCallback* callback) + btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold) { if(root0&&root1) @@ -235,11 +253,16 @@ static inline void MycollideTT( const btDbvtNode* root0, int depth=1; int treshold=btDbvt::DOUBLE_STACKSIZE-4; btAlignedObjectArray stkStack; +#ifdef USE_LOCAL_STACK + ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]); + stkStack.initializeFromBuffer(&localStack,btDbvt::DOUBLE_STACKSIZE,btDbvt::DOUBLE_STACKSIZE); +#else stkStack.resize(btDbvt::DOUBLE_STACKSIZE); +#endif stkStack[0]=btDbvt::sStkNN(root0,root1); do { btDbvt::sStkNN p=stkStack[--depth]; - if(MyIntersect(p.a->volume,p.b->volume,xform)) + if(MyIntersect(p.a->volume,p.b->volume,xform, distanceThreshold)) { if(depth>treshold) { @@ -313,6 +336,10 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb { int i; btManifoldArray manifoldArray; +#ifdef USE_LOCAL_STACK + btPersistentManifold localManifolds[4]; + manifoldArray.initializeFromBuffer(&localManifolds,0,4); +#endif btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); for (i=0;igetWorldTransform().inverse()*col1ObjWrap->getWorldTransform(); - MycollideTT(tree0->m_root,tree1->m_root,xform,&callback); + MycollideTT(tree0->m_root,tree1->m_root,xform,&callback, resultOut->m_closestPointDistanceThreshold); //printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs); @@ -381,7 +408,9 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb newChildWorldTrans0 = orgTrans0*childTrans0 ; childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0); } - + btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold); + aabbMin0 -= thresholdVec; + aabbMax0 += thresholdVec; { btTransform orgInterpolationTrans1; const btCollisionShape* childShape1 = 0; @@ -396,7 +425,8 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1); } - + aabbMin1 -= thresholdVec; + aabbMax1 += thresholdVec; if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) { diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp index 4ec9ae7138..1cb3d2e7a1 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp @@ -47,8 +47,6 @@ subject to the following restrictions: btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) { - m_numPerturbationIterations = 0; - m_minimumPointsPerturbationThreshold = 3; m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } @@ -57,15 +55,13 @@ btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc() { } -btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */) : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), m_simplexSolver(simplexSolver), m_pdSolver(pdSolver), m_ownManifold (false), m_manifoldPtr(mf), -m_lowLevelOfDetail(false), - m_numPerturbationIterations(numPerturbationIterations), -m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +m_lowLevelOfDetail(false) { (void)body0Wrap; (void)body1Wrap; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h index 18d9385a18..24d1336778 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h @@ -40,9 +40,6 @@ class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm btPersistentManifold* m_manifoldPtr; bool m_lowLevelOfDetail; - int m_numPerturbationIterations; - int m_minimumPointsPerturbationThreshold; - public: btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 912a528556..39ff7934d9 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -15,6 +15,7 @@ subject to the following restrictions: #include "btConvexConcaveCollisionAlgorithm.h" +#include "LinearMath/btQuickprof.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -29,8 +30,8 @@ subject to the following restrictions: btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), -m_isSwapped(isSwapped), -m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped) +m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped), +m_isSwapped(isSwapped) { } @@ -79,6 +80,7 @@ void btConvexTriangleCallback::clearCache() void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) { + BT_PROFILE("btConvexTriangleCallback::processTriangle"); if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax)) { @@ -116,8 +118,16 @@ partId, int triangleIndex) btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform? - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap,&triObWrap,m_manifoldPtr); - + btCollisionAlgorithm* colAlgo = 0; + + if (m_resultOut->m_closestPointDistanceThreshold > 0) + { + colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS); + } + else + { + colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS); + } const btCollisionObjectWrapper* tmpWrap = 0; if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject()) @@ -168,7 +178,8 @@ void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTr const btCollisionShape* convexShape = static_cast(m_convexBodyWrap->getCollisionShape()); //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); - btScalar extraMargin = collisionMarginTriangle; + btScalar extraMargin = collisionMarginTriangle+ resultOut->m_closestPointDistanceThreshold; + btVector3 extra(extraMargin,extraMargin,extraMargin); m_aabbMax += extra; @@ -184,7 +195,7 @@ void btConvexConcaveCollisionAlgorithm::clearCache() void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) { - + BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision"); const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap; const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap; @@ -265,6 +276,7 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) { + BT_PROFILE("processTriangle"); (void)partId; (void)triangleIndex; //do a swept sphere for now diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index e90d06eb19..93d842ef50 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -26,14 +26,16 @@ class btDispatcher; #include "btCollisionCreateFunc.h" ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. -class btConvexTriangleCallback : public btTriangleCallback +ATTRIBUTE_ALIGNED16(class) btConvexTriangleCallback : public btTriangleCallback { - const btCollisionObjectWrapper* m_convexBodyWrap; - const btCollisionObjectWrapper* m_triBodyWrap; btVector3 m_aabbMin; btVector3 m_aabbMax ; + const btCollisionObjectWrapper* m_convexBodyWrap; + const btCollisionObjectWrapper* m_triBodyWrap; + + btManifoldResult* m_resultOut; btDispatcher* m_dispatcher; @@ -41,6 +43,8 @@ class btConvexTriangleCallback : public btTriangleCallback btScalar m_collisionMarginTriangle; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + int m_triangleCount; btPersistentManifold* m_manifoldPtr; @@ -75,17 +79,19 @@ int m_triangleCount; /// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes. -class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm +ATTRIBUTE_ALIGNED16(class) btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm { - bool m_isSwapped; - btConvexTriangleCallback m_btConvexTriangleCallback; + bool m_isSwapped; + public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); virtual ~btConvexConcaveCollisionAlgorithm(); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index 7f2722aa46..b54bd48932 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -16,7 +16,7 @@ subject to the following restrictions: ///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance ///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums ///with reproduction case -//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1 +//#define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1 //#define ZERO_MARGIN #include "btConvexConvexAlgorithm.h" @@ -179,11 +179,10 @@ static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance( -btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +btConvexConvexAlgorithm::CreateFunc::CreateFunc(btConvexPenetrationDepthSolver* pdSolver) { m_numPerturbationIterations = 0; m_minimumPointsPerturbationThreshold = 3; - m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } @@ -191,9 +190,8 @@ btConvexConvexAlgorithm::CreateFunc::~CreateFunc() { } -btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), -m_simplexSolver(simplexSolver), m_pdSolver(pdSolver), m_ownManifold (false), m_manifoldPtr(mf), @@ -312,10 +310,10 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* #ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE)) { + //m_manifoldPtr->clearManifold(); + btCapsuleShape* capsuleA = (btCapsuleShape*) min0; btCapsuleShape* capsuleB = (btCapsuleShape*) min1; - // btVector3 localScalingA = capsuleA->getLocalScaling(); - // btVector3 localScalingB = capsuleB->getLocalScaling(); btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); @@ -331,6 +329,50 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* resultOut->refreshContactPoints(); return; } + + if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == SPHERE_SHAPE_PROXYTYPE)) + { + //m_manifoldPtr->clearManifold(); + + btCapsuleShape* capsuleA = (btCapsuleShape*) min0; + btSphereShape* capsuleB = (btSphereShape*) min1; + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(), + 0.,capsuleB->getRadius(),capsuleA->getUpAxis(),1, + body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold); + + if (dist=(SIMD_EPSILON*SIMD_EPSILON)); + resultOut->addContactPoint(normalOnB,pointOnBWorld,dist); + } + resultOut->refreshContactPoints(); + return; + } + + if ((min0->getShapeType() == SPHERE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE)) + { + //m_manifoldPtr->clearManifold(); + + btSphereShape* capsuleA = (btSphereShape*) min0; + btCapsuleShape* capsuleB = (btCapsuleShape*) min1; + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,0.,capsuleA->getRadius(), + capsuleB->getHalfHeight(),capsuleB->getRadius(),1,capsuleB->getUpAxis(), + body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold); + + if (dist=(SIMD_EPSILON*SIMD_EPSILON)); + resultOut->addContactPoint(normalOnB,pointOnBWorld,dist); + } + resultOut->refreshContactPoints(); + return; + } #endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER @@ -349,8 +391,8 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* btGjkPairDetector::ClosestPointInput input; - - btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); + btVoronoiSimplexSolver simplexSolver; + btGjkPairDetector gjkPairDetector( min0, min1, &simplexSolver, m_pdSolver ); //TODO: if (dispatchInfo.m_useContinuous) gjkPairDetector.setMinkowskiA(min0); gjkPairDetector.setMinkowskiB(min1); @@ -367,7 +409,7 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); //} else //{ - input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold()+resultOut->m_closestPointDistanceThreshold; // } input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; @@ -503,9 +545,11 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + worldVertsB1.resize(0); btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), body0Wrap->getWorldTransform(), - body1Wrap->getWorldTransform(), minDist-threshold, threshold, *resultOut); + body1Wrap->getWorldTransform(), minDist-threshold, threshold, worldVertsB1,worldVertsB2, + *resultOut); } if (m_ownManifold) @@ -568,8 +612,9 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* if (foundSepAxis) { + worldVertsB2.resize(0); btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), - body0Wrap->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut); + body0Wrap->getWorldTransform(), vertices, worldVertsB2,minDist-threshold, maxDist, *resultOut); } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index 51db0c6548..cd75ba12d7 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -24,6 +24,7 @@ subject to the following restrictions: #include "btCollisionCreateFunc.h" #include "btCollisionDispatcher.h" #include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil +#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h" class btConvexPenetrationDepthSolver; @@ -42,9 +43,10 @@ class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm #ifdef USE_SEPDISTANCE_UTIL2 btConvexSeparatingDistanceUtil m_sepDistance; #endif - btSimplexSolverInterface* m_simplexSolver; btConvexPenetrationDepthSolver* m_pdSolver; + btVertexArray worldVertsB1; + btVertexArray worldVertsB2; bool m_ownManifold; btPersistentManifold* m_manifoldPtr; @@ -59,7 +61,7 @@ class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm public: - btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); virtual ~btConvexConvexAlgorithm(); @@ -87,18 +89,17 @@ class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm { btConvexPenetrationDepthSolver* m_pdSolver; - btSimplexSolverInterface* m_simplexSolver; int m_numPerturbationIterations; int m_minimumPointsPerturbationThreshold; - CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + CreateFunc(btConvexPenetrationDepthSolver* pdSolver); virtual ~CreateFunc(); virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) { void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); - return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); } }; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp index d42f00a637..f6e4e57b0a 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -44,9 +44,7 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefault //btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) { - void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); - m_simplexSolver = new (mem)btVoronoiSimplexSolver(); - + void* mem = NULL; if (constructionInfo.m_useEpaPenetrationAlgorithm) { mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); @@ -59,7 +57,7 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefault //default CreationFunctions, filling the m_doubleDispatch table mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); - m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver); mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); @@ -123,6 +121,7 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefault m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); } + collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize+16)&0xffffffffffff0; if (constructionInfo.m_collisionAlgorithmPool) { m_ownsCollisionAlgorithmPool = false; @@ -192,9 +191,6 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); btAlignedFree( m_planeConvexCF); - m_simplexSolver->~btVoronoiSimplexSolver(); - btAlignedFree(m_simplexSolver); - m_pdSolver->~btConvexPenetrationDepthSolver(); btAlignedFree(m_pdSolver); @@ -202,6 +198,86 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() } +btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) +{ + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE)) + { + return m_sphereSphereCF; + } +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) + { + return m_sphereBoxCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE)) + { + return m_boxSphereCF; + } +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE)) + { + return m_sphereTriangleCF; + } + + if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE)) + { + return m_triangleSphereCF; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) + { + return m_convexPlaneCF; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) + { + return m_planeConvexCF; + } + + + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + + if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1)) + { + return m_compoundCompoundCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } + else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; + +} btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) { diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h index 2078420e19..17c7596cff 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -60,8 +60,7 @@ class btDefaultCollisionConfiguration : public btCollisionConfiguration btPoolAllocator* m_collisionAlgorithmPool; bool m_ownsCollisionAlgorithmPool; - //default simplex/penetration depth solvers - btVoronoiSimplexSolver* m_simplexSolver; + //default penetration depth solver btConvexPenetrationDepthSolver* m_pdSolver; //default CreationFunctions, filling the m_doubleDispatch table @@ -102,14 +101,10 @@ class btDefaultCollisionConfiguration : public btCollisionConfiguration } - virtual btVoronoiSimplexSolver* getSimplexSolver() - { - return m_simplexSolver; - } - - virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1); + ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm. ///By default, this feature is disabled for best performance. ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature. diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp index cfcca5654d..8c8a7c3c1e 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp @@ -28,9 +28,7 @@ int gFindSimplePairs =0; -btHashedSimplePairCache::btHashedSimplePairCache(): - m_blockedForChanges(false) -{ +btHashedSimplePairCache::btHashedSimplePairCache() { int initialAllocatedSize= 2; m_overlappingPairArray.reserve(initialAllocatedSize); growTables(); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h index e88ef97e96..186964d723 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h @@ -55,9 +55,7 @@ extern int gFindSimplePairs; class btHashedSimplePairCache { btSimplePairArray m_overlappingPairArray; - - bool m_blockedForChanges; - + protected: diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp index 73fa4e87ea..6cba442ca5 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp @@ -193,7 +193,7 @@ struct btConnectivityProcessor : public btTriangleCallback btScalar len2 = calculatedEdge.length2(); btScalar correctedAngle(0); - btVector3 calculatedNormalB = normalA; + //btVector3 calculatedNormalB = normalA; bool isConvex = false; if (len2m_planarEpsilon) @@ -213,10 +213,6 @@ struct btConnectivityProcessor : public btTriangleCallback isConvex = (dotA<0.); correctedAngle = isConvex ? ang4 : -ang4; - btQuaternion orn2(calculatedEdge,-correctedAngle); - calculatedNormalB = btMatrix3x3(orn2)*normalA; - - } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index 4b2986a008..be8e51d527 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -24,10 +24,9 @@ ContactAddedCallback gContactAddedCallback=0; -///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; -inline btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1) +btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1) { - btScalar friction = body0->getRollingFriction() * body1->getRollingFriction(); + btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction(); const btScalar MAX_FRICTION = btScalar(10.); if (friction < -MAX_FRICTION) @@ -38,6 +37,17 @@ inline btScalar calculateCombinedRollingFriction(const btCollisionObject* body0, } +btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0,const btCollisionObject* body1) +{ + btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction(); + + const btScalar MAX_FRICTION = btScalar(10.); + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; +} ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1) @@ -58,6 +68,22 @@ btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* return body0->getRestitution() * body1->getRestitution(); } +btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0,const btCollisionObject* body1) +{ + return body0->getContactDamping() + body1->getContactDamping(); +} + +btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0,const btCollisionObject* body1) +{ + + btScalar s0 = body0->getContactStiffness(); + btScalar s1 = body1->getContactStiffness(); + + btScalar tmp0 = btScalar(1)/s0; + btScalar tmp1 = btScalar(1)/s1; + btScalar combinedStiffness = btScalar(1) / (tmp0+tmp1); + return combinedStiffness; +} btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) @@ -70,6 +96,7 @@ btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,con m_index0(-1), m_index1(-1) #endif //DEBUG_PART_INDEX + , m_closestPointDistanceThreshold(0) { } @@ -109,6 +136,16 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b newPt.m_combinedFriction = calculateCombinedFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); newPt.m_combinedRollingFriction = calculateCombinedRollingFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + newPt.m_combinedSpinningFriction = calculateCombinedSpinningFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + + if ( (m_body0Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) || + (m_body1Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING)) + { + newPt.m_combinedContactDamping1 = calculateCombinedContactDamping(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + newPt.m_combinedContactStiffness1 = calculateCombinedContactStiffness(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING; + } + btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 977b9a02fc..86bbc3f729 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -49,17 +49,19 @@ class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result int m_index0; int m_index1; - + public: btManifoldResult() -#ifdef DEBUG_PART_INDEX : +#ifdef DEBUG_PART_INDEX + m_partId0(-1), m_partId1(-1), m_index0(-1), m_index1(-1) #endif //DEBUG_PART_INDEX + m_closestPointDistanceThreshold(0) { } @@ -142,9 +144,15 @@ class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result return m_body1Wrap->getCollisionObject(); } + btScalar m_closestPointDistanceThreshold; + /// in the future we can let the user override the methods to combine restitution and friction static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1); static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1); + static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1); + static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0,const btCollisionObject* body1); + static btScalar calculateCombinedContactDamping(const btCollisionObject* body0,const btCollisionObject* body1); + static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0,const btCollisionObject* body1); }; #endif //BT_MANIFOLD_RESULT_H diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp index 36ba21f5bb..27eaec3059 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -12,6 +12,7 @@ subject to the following restrictions: 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. */ +#define CLEAR_MANIFOLD 1 #include "btSphereSphereCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" @@ -62,7 +63,7 @@ void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObject #endif ///iff distance positive, don't generate a new contact - if ( len > (radius0+radius1)) + if ( len > (radius0+radius1+resultOut->m_closestPointDistanceThreshold)) { #ifndef CLEAR_MANIFOLD resultOut->refreshContactPoints(); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index 280a4d355f..86d4e74400 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -56,7 +56,7 @@ void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObje /// report a contact. internally this will be kept persistent, and contact reduction is done resultOut->setPersistentManifold(m_manifoldPtr); - SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()); + SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold); btDiscreteCollisionDetectorInterface::ClosestPointInput input; input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp index ace4cfa264..0940da1a4b 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @@ -245,16 +245,18 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co btStridingMeshInterface* m_meshInterface; btTriangleCallback* m_callback; btVector3 m_triangle[3]; - + int m_numOverlap; MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) :m_meshInterface(meshInterface), - m_callback(callback) + m_callback(callback), + m_numOverlap(0) { } virtual void processNode(int nodeSubPart, int nodeTriangleIndex) { + m_numOverlap++; const unsigned char *vertexbase; int numverts; PHY_ScalarType type; @@ -321,8 +323,7 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); - - + #endif//DISABLE_BVH diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index 493d635539..1fa4995d16 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -39,7 +39,11 @@ ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape bool m_useQuantizedAabbCompression; bool m_ownsBvh; +#ifdef __clang__ + bool m_pad[11] __attribute__((unused));////need padding due to alignment +#else bool m_pad[11];////need padding due to alignment +#endif public: diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index 864df26e93..0345501ce2 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -16,11 +16,11 @@ subject to the following restrictions: #include "btCapsuleShape.h" -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" #include "LinearMath/btQuaternion.h" btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape () { + m_collisionMargin = radius; m_shapeType = CAPSULE_SHAPE_PROXYTYPE; m_upAxis = 1; m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); @@ -48,14 +48,13 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter btVector3 vtx; btScalar newDot; - btScalar radius = getRadius(); - + { btVector3 pos(0,0,0); pos[getUpAxis()] = getHalfHeight(); - vtx = pos +vec*(radius) - vec * getMargin(); + vtx = pos; newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -67,7 +66,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter btVector3 pos(0,0,0); pos[getUpAxis()] = -getHalfHeight(); - vtx = pos +vec*(radius) - vec * getMargin(); + vtx = pos; newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -84,8 +83,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter { - btScalar radius = getRadius(); - + for (int j=0;j maxDot) { @@ -107,7 +105,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter { btVector3 pos(0,0,0); pos[getUpAxis()] = -getHalfHeight(); - vtx = pos +vec*(radius) - vec * getMargin(); + vtx = pos; newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -133,11 +131,9 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con btVector3 halfExtents(radius,radius,radius); halfExtents[getUpAxis()]+=getHalfHeight(); - btScalar margin = CONVEX_DISTANCE_MARGIN; - - btScalar lx=btScalar(2.)*(halfExtents[0]+margin); - btScalar ly=btScalar(2.)*(halfExtents[1]+margin); - btScalar lz=btScalar(2.)*(halfExtents[2]+margin); + btScalar lx=btScalar(2.)*(halfExtents[0]); + btScalar ly=btScalar(2.)*(halfExtents[1]); + btScalar lz=btScalar(2.)*(halfExtents[2]); const btScalar x2 = lx*lx; const btScalar y2 = ly*ly; const btScalar z2 = lz*lz; @@ -151,6 +147,7 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) { + m_collisionMargin = radius; m_upAxis = 0; m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); } @@ -162,6 +159,7 @@ btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) { + m_collisionMargin = radius; m_upAxis = 2; m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h index f8c55ace4e..aa65d54398 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -48,21 +48,13 @@ ATTRIBUTE_ALIGNED16(class) btCapsuleShape : public btConvexInternalShape virtual void setMargin(btScalar collisionMargin) { - //correct the m_implicitShapeDimensions for the margin - btVector3 oldMargin(getMargin(),getMargin(),getMargin()); - btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; - - btConvexInternalShape::setMargin(collisionMargin); - btVector3 newMargin(getMargin(),getMargin(),getMargin()); - m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; - + //don't override the margin for capsules, their entire radius == margin } virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const { btVector3 halfExtents(getRadius(),getRadius(),getRadius()); halfExtents[m_upAxis] = getRadius() + getHalfHeight(); - halfExtents += btVector3(getMargin(),getMargin(),getMargin()); btMatrix3x3 abs_b = t.getBasis().absolute(); btVector3 center = t.getOrigin(); btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); @@ -94,14 +86,12 @@ ATTRIBUTE_ALIGNED16(class) btCapsuleShape : public btConvexInternalShape virtual void setLocalScaling(const btVector3& scaling) { - btVector3 oldMargin(getMargin(),getMargin(),getMargin()); - btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; - btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; - - btConvexInternalShape::setLocalScaling(scaling); - - m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; - + btVector3 unScaledImplicitShapeDimensions = m_implicitShapeDimensions / m_localScaling; + btConvexInternalShape::setLocalScaling(scaling); + m_implicitShapeDimensions = (unScaledImplicitShapeDimensions * scaling); + //update m_collisionMargin, since entire radius==margin + int radiusAxis = (m_upAxis+2)%3; + m_collisionMargin = m_implicitShapeDimensions[radiusAxis]; } virtual btVector3 getAnisotropicRollingFrictionDirection() const diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h index 5e86568005..6c4916fbd4 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -48,7 +48,7 @@ ATTRIBUTE_ALIGNED16(class) btCollisionShape virtual void getBoundingSphere(btVector3& center,btScalar& radius) const; - ///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. + ///getAngularMotionDisc returns the maximum radius needed for Conservative Advancement to handle time-of-impact with rotations. virtual btScalar getAngularMotionDisc() const; virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const; diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConeShape.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConeShape.h index 4a0df0d558..46d78d148c 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConeShape.h @@ -43,6 +43,15 @@ ATTRIBUTE_ALIGNED16(class) btConeShape : public btConvexInternalShape btScalar getRadius() const { return m_radius;} btScalar getHeight() const { return m_height;} + void setRadius(const btScalar radius) + { + m_radius = radius; + } + void setHeight(const btScalar height) + { + m_height = height; + } + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp index 0623e351a9..c1aa6ca468 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp @@ -22,6 +22,8 @@ subject to the following restrictions: #include "LinearMath/btQuaternion.h" #include "LinearMath/btSerializer.h" +#include "btConvexPolyhedron.h" +#include "LinearMath/btConvexHullComputer.h" btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape () { @@ -121,10 +123,17 @@ btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const } - - - - +void btConvexHullShape::optimizeConvexHull() +{ + btConvexHullComputer conv; + conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3),m_unscaledPoints.size(),0.f,0.f); + int numVerts = conv.vertices.size(); + m_unscaledPoints.resize(0); + for (int i=0;i1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false; return true; } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp index b56d72917d..8d7fb054d6 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -230,14 +230,13 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV btScalar halfHeight = capsuleShape->getHalfHeight(); int capsuleUpAxis = capsuleShape->getUpAxis(); - btScalar radius = capsuleShape->getRadius(); btVector3 supVec(0,0,0); btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); btVector3 vec = vec0; btScalar lenSqr = vec.length2(); - if (lenSqr < btScalar(0.0001)) + if (lenSqr < SIMD_EPSILON*SIMD_EPSILON) { vec.setValue(1,0,0); } else @@ -251,8 +250,7 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV btVector3 pos(0,0,0); pos[capsuleUpAxis] = halfHeight; - //vtx = pos +vec*(radius); - vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); + vtx = pos; newDot = vec.dot(vtx); @@ -266,8 +264,7 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV btVector3 pos(0,0,0); pos[capsuleUpAxis] = -halfHeight; - //vtx = pos +vec*(radius); - vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); + vtx = pos; newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -427,7 +424,6 @@ void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius()); int m_upAxis = capsuleShape->getUpAxis(); halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight(); - halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual()); btMatrix3x3 abs_b = t.getBasis().absolute(); btVector3 center = t.getOrigin(); btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp index a7362ea01f..88f6c4dcb0 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -75,7 +75,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala int inner_count = MIN( numSpheres - k, 128 ); for( long i = 0; i < inner_count; i++ ) { - temp[i] = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin(); + temp[i] = (*pos)*m_localScaling +vec*m_localScaling*(*rad) - vec * getMargin(); pos++; rad++; } @@ -113,7 +113,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala int inner_count = MIN( numSpheres - k, 128 ); for( long i = 0; i < inner_count; i++ ) { - temp[i] = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin(); + temp[i] = (*pos)*m_localScaling +vec*m_localScaling*(*rad) - vec * getMargin(); pos++; rad++; } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h index 2b92ab7d1b..5ebaede4a8 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h @@ -25,7 +25,6 @@ subject to the following restrictions: ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape { btAlignedObjectArray m_materialList; - int ** m_triangleMaterials; public: diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h index f85a94cb4c..3e5675f729 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h @@ -122,7 +122,7 @@ class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm checkManifold(body0Wrap,body1Wrap); btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm( - body0Wrap,body1Wrap,getLastManifold()); + body0Wrap,body1Wrap,getLastManifold(), BT_CONTACT_POINT_ALGORITHMS); return convex_algorithm ; } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp index ac8efdf383..30c85e3fff 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp @@ -23,6 +23,59 @@ subject to the following restrictions: #include "btGImpactMassUtil.h" +btGImpactMeshShapePart::btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part ) +{ + // moved from .h to .cpp because of conditional compilation + // (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to + // avoid using it in h files) + m_primitive_manager.m_meshInterface = meshInterface; + m_primitive_manager.m_part = part; + m_box_set.setPrimitiveManager( &m_primitive_manager ); +#if BT_THREADSAFE + // If threadsafe is requested, this object uses a different lock/unlock + // model with the btStridingMeshInterface -- lock once when the object is constructed + // and unlock once in the destructor. + // The other way of locking and unlocking for each collision check in the narrowphase + // is not threadsafe. Note these are not thread-locks, they are calls to the meshInterface's + // getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of + // pointers. In theory a client could override the lock function to do all sorts of + // things like reading data from GPU memory, or decompressing data on the fly, but such things + // do not seem all that likely or useful, given the performance cost. + m_primitive_manager.lock(); +#endif +} + +btGImpactMeshShapePart::~btGImpactMeshShapePart() +{ + // moved from .h to .cpp because of conditional compilation +#if BT_THREADSAFE + m_primitive_manager.unlock(); +#endif +} + +void btGImpactMeshShapePart::lockChildShapes() const +{ + // moved from .h to .cpp because of conditional compilation +#if ! BT_THREADSAFE + // called in the narrowphase -- not threadsafe! + void * dummy = (void*) ( m_box_set.getPrimitiveManager() ); + TrimeshPrimitiveManager * dummymanager = static_cast( dummy ); + dummymanager->lock(); +#endif +} + +void btGImpactMeshShapePart::unlockChildShapes() const +{ + // moved from .h to .cpp because of conditional compilation +#if ! BT_THREADSAFE + // called in the narrowphase -- not threadsafe! + void * dummy = (void*) ( m_box_set.getPrimitiveManager() ); + TrimeshPrimitiveManager * dummymanager = static_cast( dummy ); + dummymanager->unlock(); +#endif +} + + #define CALC_EXACT_INERTIA 1 diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.h b/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.h index 3d1f48d477..9d7e40562c 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/Gimpact/btGImpactShape.h @@ -722,17 +722,8 @@ class btGImpactMeshShapePart : public btGImpactShapeInterface m_box_set.setPrimitiveManager(&m_primitive_manager); } - - btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part) - { - m_primitive_manager.m_meshInterface = meshInterface; - m_primitive_manager.m_part = part; - m_box_set.setPrimitiveManager(&m_primitive_manager); - } - - virtual ~btGImpactMeshShapePart() - { - } + btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part ); + virtual ~btGImpactMeshShapePart(); //! if true, then its children must get transforms. virtual bool childrenHasTransform() const @@ -742,19 +733,8 @@ class btGImpactMeshShapePart : public btGImpactShapeInterface //! call when reading child shapes - virtual void lockChildShapes() const - { - void * dummy = (void*)(m_box_set.getPrimitiveManager()); - TrimeshPrimitiveManager * dummymanager = static_cast(dummy); - dummymanager->lock(); - } - - virtual void unlockChildShapes() const - { - void * dummy = (void*)(m_box_set.getPrimitiveManager()); - TrimeshPrimitiveManager * dummymanager = static_cast(dummy); - dummymanager->unlock(); - } + virtual void lockChildShapes() const; + virtual void unlockChildShapes() const; //! Gets the number of children virtual int getNumChildShapes() const diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp index 3268f06c2f..eefb974bbd 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -41,21 +41,38 @@ namespace gjkepa2_impl /* GJK */ #define GJK_MAX_ITERATIONS 128 -#define GJK_ACCURARY ((btScalar)0.0001) -#define GJK_MIN_DISTANCE ((btScalar)0.0001) -#define GJK_DUPLICATED_EPS ((btScalar)0.0001) + +#ifdef BT_USE_DOUBLE_PRECISION + #define GJK_ACCURACY ((btScalar)1e-12) + #define GJK_MIN_DISTANCE ((btScalar)1e-12) + #define GJK_DUPLICATED_EPS ((btScalar)1e-12) +#else + #define GJK_ACCURACY ((btScalar)0.0001) + #define GJK_MIN_DISTANCE ((btScalar)0.0001) + #define GJK_DUPLICATED_EPS ((btScalar)0.0001) +#endif //BT_USE_DOUBLE_PRECISION + + #define GJK_SIMPLEX2_EPS ((btScalar)0.0) #define GJK_SIMPLEX3_EPS ((btScalar)0.0) #define GJK_SIMPLEX4_EPS ((btScalar)0.0) /* EPA */ -#define EPA_MAX_VERTICES 64 -#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) +#define EPA_MAX_VERTICES 128 #define EPA_MAX_ITERATIONS 255 -#define EPA_ACCURACY ((btScalar)0.0001) -#define EPA_FALLBACK (10*EPA_ACCURACY) -#define EPA_PLANE_EPS ((btScalar)0.00001) -#define EPA_INSIDE_EPS ((btScalar)0.01) + +#ifdef BT_USE_DOUBLE_PRECISION + #define EPA_ACCURACY ((btScalar)1e-12) + #define EPA_PLANE_EPS ((btScalar)1e-14) + #define EPA_INSIDE_EPS ((btScalar)1e-9) +#else + #define EPA_ACCURACY ((btScalar)0.0001) + #define EPA_PLANE_EPS ((btScalar)0.00001) + #define EPA_INSIDE_EPS ((btScalar)0.01) +#endif + +#define EPA_FALLBACK (10*EPA_ACCURACY) +#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) // Shorthands @@ -242,7 +259,7 @@ namespace gjkepa2_impl /* Check for termination */ const btScalar omega=btDot(m_ray,w)/rl; alpha=btMax(omega,alpha); - if(((rl-alpha)-(GJK_ACCURARY*rl))<=0) + if(((rl-alpha)-(GJK_ACCURACY*rl))<=0) {/* Return old simplex */ removevertice(m_simplices[m_current]); break; @@ -1015,7 +1032,7 @@ bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, /* Symbols cleanup */ #undef GJK_MAX_ITERATIONS -#undef GJK_ACCURARY +#undef GJK_ACCURACY #undef GJK_MIN_DISTANCE #undef GJK_DUPLICATED_EPS #undef GJK_SIMPLEX2_EPS diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index 4c8ff2fab4..257b026d9b 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -30,7 +30,13 @@ subject to the following restrictions: #endif //must be above the machine epsilon -#define REL_ERROR2 btScalar(1.0e-6) +#ifdef BT_USE_DOUBLE_PRECISION + #define REL_ERROR2 btScalar(1.0e-12) + btScalar gGjkEpaPenetrationTolerance = 1e-7; +#else + #define REL_ERROR2 btScalar(1.0e-6) + btScalar gGjkEpaPenetrationTolerance = 0.001; +#endif //temp globals, to improve GJK/EPA/penetration calculations int gNumDeepPenetrationChecks = 0; @@ -275,7 +281,7 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu btScalar lenSqr =m_cachedSeparatingAxis.length2(); //valid normal - if (lenSqr < 0.0001) + if (lenSqr < REL_ERROR2) { m_degenerateSimplex = 5; } @@ -300,7 +306,7 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu } bool catchDegeneratePenetrationCase = - (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01)); + (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < gGjkEpaPenetrationTolerance)); //if (checkPenetration && !isValid) if (checkPenetration && (!isValid || catchDegeneratePenetrationCase )) @@ -339,6 +345,7 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu { tmpNormalInB /= btSqrt(lenSqr); btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length(); + m_lastUsedMethod = 3; //only replace valid penetrations when the result is deeper (check) if (!isValid || (distance2 < distance)) { @@ -346,9 +353,9 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu pointOnA = tmpPointOnA; pointOnB = tmpPointOnB; normalInB = tmpNormalInB; - + isValid = true; - m_lastUsedMethod = 3; + } else { m_lastUsedMethod = 8; @@ -403,6 +410,47 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu m_cachedSeparatingAxis = normalInB; m_cachedSeparatingDistance = distance; + { + ///todo: need to track down this EPA penetration solver degeneracy + ///the penetration solver reports penetration but the contact normal + ///connecting the contact points is pointing in the opposite direction + ///until then, detect the issue and revert the normal + + btScalar d1=0; + { + btVector3 seperatingAxisInA = (normalInB)* input.m_transformA.getBasis(); + btVector3 seperatingAxisInB = -normalInB* input.m_transformB.getBasis(); + + + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); + + btVector3 pWorld = localTransA(pInA); + btVector3 qWorld = localTransB(qInB); + btVector3 w = pWorld - qWorld; + d1 = (-normalInB).dot(w); + } + btScalar d0 = 0.f; + { + btVector3 seperatingAxisInA = (-normalInB)* input.m_transformA.getBasis(); + btVector3 seperatingAxisInB = normalInB* input.m_transformB.getBasis(); + + + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); + + btVector3 pWorld = localTransA(pInA); + btVector3 qWorld = localTransB(qInB); + btVector3 w = pWorld - qWorld; + d0 = normalInB.dot(w); + } + if (d1>d0) + { + m_lastUsedMethod = 10; + normalInB*=-1; + } + + } output.addContactPoint( normalInB, pointOnB+positionOffset, diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h index e40fb1d3db..04ab54ed90 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -35,7 +35,13 @@ typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow; typedef btConstraintRow PfxConstraintRow; #endif //PFX_USE_FREE_VECTORMATH - +enum btContactPointFlags +{ + BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED=1, + BT_CONTACT_FLAG_HAS_CONTACT_CFM=2, + BT_CONTACT_FLAG_HAS_CONTACT_ERP=4, + BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8, +}; /// ManifoldContactPoint collects and maintains persistent contactpoints. /// used to improve stability and performance of rigidbody dynamics response. @@ -44,14 +50,15 @@ class btManifoldPoint public: btManifoldPoint() :m_userPersistentData(0), - m_lateralFrictionInitialized(false), - m_appliedImpulse(0.f), + m_contactPointFlags(0), + m_appliedImpulse(0.f), m_appliedImpulseLateral1(0.f), m_appliedImpulseLateral2(0.f), m_contactMotion1(0.f), m_contactMotion2(0.f), - m_contactCFM1(0.f), - m_contactCFM2(0.f), + m_contactCFM(0.f), + m_contactERP(0.f), + m_frictionCFM(0.f), m_lifeTime(0) { } @@ -65,16 +72,18 @@ class btManifoldPoint m_distance1( distance ), m_combinedFriction(btScalar(0.)), m_combinedRollingFriction(btScalar(0.)), - m_combinedRestitution(btScalar(0.)), + m_combinedSpinningFriction(btScalar(0.)), + m_combinedRestitution(btScalar(0.)), m_userPersistentData(0), - m_lateralFrictionInitialized(false), - m_appliedImpulse(0.f), + m_contactPointFlags(0), + m_appliedImpulse(0.f), m_appliedImpulseLateral1(0.f), m_appliedImpulseLateral2(0.f), m_contactMotion1(0.f), m_contactMotion2(0.f), - m_contactCFM1(0.f), - m_contactCFM2(0.f), + m_contactCFM(0.f), + m_contactERP(0.f), + m_frictionCFM(0.f), m_lifeTime(0) { @@ -91,8 +100,9 @@ class btManifoldPoint btScalar m_distance1; btScalar m_combinedFriction; - btScalar m_combinedRollingFriction; - btScalar m_combinedRestitution; + btScalar m_combinedRollingFriction;//torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever + btScalar m_combinedSpinningFriction;//torsional friction around contact normal, useful for grasping objects + btScalar m_combinedRestitution; //BP mod, store contact triangles. int m_partId0; @@ -101,15 +111,28 @@ class btManifoldPoint int m_index1; mutable void* m_userPersistentData; - bool m_lateralFrictionInitialized; - + //bool m_lateralFrictionInitialized; + int m_contactPointFlags; + btScalar m_appliedImpulse; btScalar m_appliedImpulseLateral1; btScalar m_appliedImpulseLateral2; btScalar m_contactMotion1; btScalar m_contactMotion2; - btScalar m_contactCFM1; - btScalar m_contactCFM2; + + union + { + btScalar m_contactCFM; + btScalar m_combinedContactStiffness1; + }; + + union + { + btScalar m_contactERP; + btScalar m_combinedContactDamping1; + }; + + btScalar m_frictionCFM; int m_lifeTime;//lifetime of the contactpoint in frames diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index 2ceaab750f..3b82be1929 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -51,8 +51,8 @@ enum btContactManifoldTypes ///note that some pairs of objects might have more then one contact manifold. -ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject -//ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject +//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject +ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject { btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE]; @@ -163,7 +163,7 @@ ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject //get rid of duplicated userPersistentData pointer m_pointCache[lastUsedIndex].m_userPersistentData = 0; m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f; - m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false; + m_pointCache[lastUsedIndex].m_contactPointFlags = 0; m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f; m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f; m_pointCache[lastUsedIndex].m_lifeTime = 0; @@ -190,16 +190,11 @@ ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject void* cache = m_pointCache[insertIndex].m_userPersistentData; m_pointCache[insertIndex] = newPoint; - m_pointCache[insertIndex].m_userPersistentData = cache; m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; - m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; - m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; - m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; - m_pointCache[insertIndex].m_lifeTime = lifeTime; #else diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp index ea131f0c48..ea380bc5f1 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp @@ -116,7 +116,7 @@ static int gActualSATPairTests=0; inline bool IsAlmostZero(const btVector3& v) { - if(fabsf(v.x())>1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false; return true; } @@ -411,9 +411,9 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& return true; } -void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut) +void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut) { - btVertexArray worldVertsB2; + worldVertsB2.resize(0); btVertexArray* pVtxIn = &worldVertsB1; btVertexArray* pVtxOut = &worldVertsB2; pVtxOut->reserve(pVtxIn->size()); @@ -527,7 +527,7 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin -void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut) +void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut) { btVector3 separatingNormal = separatingNormal1.normalized(); @@ -552,7 +552,7 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin } } } - btVertexArray worldVertsB1; + worldVertsB1.resize(0); { const btFace& polyB = hullB.m_faces[closestFaceB]; const int numVertices = polyB.m_indices.size(); @@ -565,6 +565,6 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin if (closestFaceB>=0) - clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut); + clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, worldVertsB2,minDist, maxDist,resultOut); } diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h index b87bd4f324..30e3db687b 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h @@ -32,8 +32,11 @@ typedef btAlignedObjectArray btVertexArray; // Clips a face to the back of a plane struct btPolyhedralContactClipping { - static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut); - static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut); + + static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut); + + static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut); + static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut); diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp index a775198ab2..23b4f79cfc 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -294,7 +294,10 @@ bool btVoronoiSimplexSolver::inSimplex(const btVector3& w) #else if (m_simplexVectorW[i] == w) #endif + { found = true; + break; + } } //check in case lastW is already removed diff --git a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h index 2f389e27e3..80fd490f4e 100644 --- a/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h +++ b/Source/ThirdParty/Bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h @@ -26,8 +26,12 @@ subject to the following restrictions: ///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure #define BT_USE_EQUAL_VERTEX_THRESHOLD -#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f +#ifdef BT_USE_DOUBLE_PRECISION +#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 1e-12f +#else +#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f +#endif//BT_USE_DOUBLE_PRECISION struct btUsageBitfield{ btUsageBitfield() diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h index dffb06dfe9..c3a3ac6c8d 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h @@ -37,7 +37,7 @@ class btCharacterControllerInterface : public btActionInterface virtual void preStep ( btCollisionWorld* collisionWorld) = 0; virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0; virtual bool canJump () const = 0; - virtual void jump () = 0; + virtual void jump(const btVector3& dir = btVector3()) = 0; virtual bool onGround () const = 0; virtual void setUpInterpolate (bool value) = 0; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp index 31faf1df5e..339bb6fc17 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp @@ -132,30 +132,37 @@ btVector3 btKinematicCharacterController::perpindicularComponent (const btVector return direction - parallelComponent(direction, normal); } -btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis) +btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up) { - m_upAxis = upAxis; - m_addedMargin = 0.02; - m_walkDirection.setValue(0,0,0); - m_useGhostObjectSweepTest = true; m_ghostObject = ghostObject; - m_stepHeight = stepHeight; + m_up.setValue(0.0f, 0.0f, 1.0f); + m_jumpAxis.setValue(0.0f, 0.0f, 1.0f); + setUp(up); + setStepHeight(stepHeight); + m_addedMargin = 0.02; + m_walkDirection.setValue(0.0,0.0,0.0); + m_AngVel.setValue(0.0, 0.0, 0.0); + m_useGhostObjectSweepTest = true; m_turnAngle = btScalar(0.0); m_convexShape=convexShape; m_useWalkDirection = true; // use walk direction by default, legacy behavior m_velocityTimeInterval = 0.0; m_verticalVelocity = 0.0; m_verticalOffset = 0.0; - m_gravity = 9.8 * 3 ; // 3G acceleration. + m_gravity = 9.8 * 3.0 ; // 3G acceleration. m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s. m_jumpSpeed = 10.0; // ? + m_SetjumpSpeed = m_jumpSpeed; m_wasOnGround = false; m_wasJumping = false; m_interpolateUp = true; setMaxSlope(btRadians(45.0)); - m_currentStepOffset = 0; + m_currentStepOffset = 0.0; + m_maxPenetrationDepth = 0.2; full_drop = false; bounce_fix = false; + m_linearDamping = btScalar(0.0); + m_angularDamping = btScalar(0.0); } btKinematicCharacterController::~btKinematicCharacterController () @@ -190,7 +197,7 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); - btScalar maxPen = btScalar(0.0); +// btScalar maxPen = btScalar(0.0); for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++) { m_manifoldArray.resize(0); @@ -198,10 +205,13 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; btCollisionObject* obj0 = static_cast(collisionPair->m_pProxy0->m_clientObject); - btCollisionObject* obj1 = static_cast(collisionPair->m_pProxy1->m_clientObject); + btCollisionObject* obj1 = static_cast(collisionPair->m_pProxy1->m_clientObject); if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse())) continue; + + if (!needsCollision(obj0, obj1)) + continue; if (collisionPair->m_algorithm) collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray); @@ -217,14 +227,15 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* btScalar dist = pt.getDistance(); - if (dist < 0.0) + if (dist < -m_maxPenetrationDepth) { - if (dist < maxPen) - { - maxPen = dist; - m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? + // TODO: cause problems on slopes, not sure if it is needed + //if (dist < maxPen) + //{ + // maxPen = dist; + // m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? - } + //} m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2); penetration = true; } else { @@ -244,18 +255,28 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* void btKinematicCharacterController::stepUp ( btCollisionWorld* world) { + btScalar stepHeight = 0.0f; + if (m_verticalVelocity < 0.0) + stepHeight = m_stepHeight; + // phase 1: up btTransform start, end; - m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f)); start.setIdentity (); end.setIdentity (); /* FIXME: Handle penetration properly */ - start.setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin)); + start.setOrigin(m_currentPosition); + + m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f)); + m_currentPosition = m_targetPosition; + end.setOrigin (m_targetPosition); - btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071)); + start.setRotation(m_currentOrientation); + end.setRotation(m_targetOrientation); + + btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -m_up, m_maxSlopeCosine); callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; @@ -265,29 +286,61 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world) } else { - world->convexSweepTest (m_convexShape, start, end, callback); + world->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration); } - - if (callback.hasHit()) + + if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject)) { // Only modify the position if the hit was a slope and not a wall or ceiling. - if(callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0) + if (callback.m_hitNormalWorld.dot(m_up) > 0.0) { // we moved up only a fraction of the step height - m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction; + m_currentStepOffset = stepHeight * callback.m_closestHitFraction; if (m_interpolateUp == true) m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); else m_currentPosition = m_targetPosition; } - m_verticalVelocity = 0.0; - m_verticalOffset = 0.0; + + btTransform& xform = m_ghostObject->getWorldTransform(); + xform.setOrigin(m_currentPosition); + m_ghostObject->setWorldTransform(xform); + + // fix penetration if we hit a ceiling for example + int numPenetrationLoops = 0; + m_touchingContact = false; + while (recoverFromPenetration(world)) + { + numPenetrationLoops++; + m_touchingContact = true; + if (numPenetrationLoops > 4) + { + //printf("character could not recover from penetration = %d\n", numPenetrationLoops); + break; + } + } + m_targetPosition = m_ghostObject->getWorldTransform().getOrigin(); + m_currentPosition = m_targetPosition; + + if (m_verticalOffset > 0) + { + m_verticalOffset = 0.0; + m_verticalVelocity = 0.0; + m_currentStepOffset = m_stepHeight; + } } else { - m_currentStepOffset = m_stepHeight; + m_currentStepOffset = stepHeight; m_currentPosition = m_targetPosition; } } +bool btKinematicCharacterController::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1) +{ + bool collides = (body0->getBroadphaseHandle()->m_collisionFilterGroup & body1->getBroadphaseHandle()->m_collisionFilterMask) != 0; + collides = collides && (body1->getBroadphaseHandle()->m_collisionFilterGroup & body0->getBroadphaseHandle()->m_collisionFilterMask); + return collides; +} + void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag) { btVector3 movementDirection = m_targetPosition - m_currentPosition; @@ -330,6 +383,7 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]); // phase 2: forward and strafe btTransform start, end; + m_targetPosition = m_currentPosition + walkMove; start.setIdentity (); @@ -339,15 +393,6 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co btScalar distance2 = (m_currentPosition-m_targetPosition).length2(); // printf("distance2=%f\n",distance2); - if (m_touchingContact) - { - if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0)) - { - //interferes with step movement - //updateTargetPositionBasedOnCollision (m_touchingNormal); - } - } - int maxIter = 10; while (fraction > btScalar(0.01) && maxIter-- > 0) @@ -356,6 +401,9 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co end.setOrigin (m_targetPosition); btVector3 sweepDirNegative(m_currentPosition - m_targetPosition); + start.setRotation(m_currentOrientation); + end.setRotation(m_targetOrientation); + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0)); callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; @@ -364,21 +412,23 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co btScalar margin = m_convexShape->getMargin(); m_convexShape->setMargin(margin + m_addedMargin); - - if (m_useGhostObjectSweepTest) - { - m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); - } else + if (!(start == end)) { - collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } + else + { + collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } } - m_convexShape->setMargin(margin); fraction -= callback.m_closestHitFraction; - if (callback.hasHit()) + if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject)) { // we moved only a fraction //btScalar hitDistance; @@ -403,14 +453,11 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co break; } - } else { - // we moved whole way - m_currentPosition = m_targetPosition; } - - // if (callback.m_closestHitFraction == 0.f) - // break; - + else + { + m_currentPosition = m_targetPosition; + } } } @@ -421,27 +468,30 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld // phase 3: down /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0; - btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep); + btVector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep); btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt; - btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity; + btVector3 gravity_drop = m_up * downVelocity; m_targetPosition -= (step_drop + gravity_drop);*/ btVector3 orig_position = m_targetPosition; btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; + if (m_verticalVelocity > 0.0) + return; + if(downVelocity > 0.0 && downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping)) downVelocity = m_fallSpeed; - btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity); m_targetPosition -= step_drop; - btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine); + btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, m_up, m_maxSlopeCosine); callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; - btKinematicClosestNotMeConvexResultCallback callback2 (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine); + btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, m_up, m_maxSlopeCosine); callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; @@ -455,6 +505,9 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld start.setOrigin (m_currentPosition); end.setOrigin (m_targetPosition); + start.setRotation(m_currentOrientation); + end.setRotation(m_targetOrientation); + //set double test for 2x the step drop, to check for a large drop vs small drop end_double.setOrigin (m_targetPosition - step_drop); @@ -462,7 +515,7 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld { m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); - if (!callback.hasHit()) + if (!callback.hasHit() && m_ghostObject->hasContactResponse()) { //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial) m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); @@ -471,30 +524,34 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld { collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); - if (!callback.hasHit()) - { - //test a double fall height, to see if the character should interpolate it's fall (large) or not (small) - collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); - } + if (!callback.hasHit() && m_ghostObject->hasContactResponse()) + { + //test a double fall height, to see if the character should interpolate it's fall (large) or not (small) + collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } } btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; - bool has_hit = false; + bool has_hit; if (bounce_fix == true) - has_hit = callback.hasHit() || callback2.hasHit(); + has_hit = (callback.hasHit() || callback2.hasHit()) && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject); else - has_hit = callback2.hasHit(); + has_hit = callback2.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback2.m_hitCollisionObject); + + btScalar stepHeight = 0.0f; + if (m_verticalVelocity < 0.0) + stepHeight = m_stepHeight; - if(downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit == true && runonce == false + if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false && (m_wasOnGround || !m_wasJumping)) { //redo the velocity calculation when falling a small amount, for fast stairs motion //for larger falls, use the smoother/slower interpolated movement by not touching the target position m_targetPosition = orig_position; - downVelocity = m_stepHeight; + downVelocity = stepHeight; - btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + step_drop = m_up * (m_currentStepOffset + downVelocity); m_targetPosition -= step_drop; runonce = true; continue; //re-run previous tests @@ -502,10 +559,9 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld break; } - if (callback.hasHit() || runonce == true) + if ((m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))) || runonce == true) { // we dropped a fraction of the height -> hit floor - btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2; //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY()); @@ -513,10 +569,10 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld if (bounce_fix == true) { if (full_drop == true) - m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); - else - //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually - m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction); + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + else + //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction); } else m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); @@ -528,7 +584,7 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld m_wasJumping = false; } else { // we dropped the full height - + full_drop = true; if (bounce_fix == true) @@ -538,7 +594,7 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld { m_targetPosition += step_drop; //undo previous target change downVelocity = m_fallSpeed; - step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + step_drop = m_up * (m_currentStepOffset + downVelocity); m_targetPosition -= step_drop; } } @@ -579,21 +635,63 @@ btScalar timeInterval m_velocityTimeInterval += timeInterval; } -void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld ) +void btKinematicCharacterController::setAngularVelocity(const btVector3& velocity) { - m_verticalVelocity = 0.0; - m_verticalOffset = 0.0; - m_wasOnGround = false; - m_wasJumping = false; - m_walkDirection.setValue(0,0,0); - m_velocityTimeInterval = 0.0; + m_AngVel = velocity; +} - //clear pair cache - btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache(); - while (cache->getOverlappingPairArray().size() > 0) - { - cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher()); - } +const btVector3& btKinematicCharacterController::getAngularVelocity() const +{ + return m_AngVel; +} + +void btKinematicCharacterController::setLinearVelocity(const btVector3& velocity) +{ + m_walkDirection = velocity; + + // HACK: if we are moving in the direction of the up, treat it as a jump :( + if (m_walkDirection.length2() > 0) + { + btVector3 w = velocity.normalized(); + btScalar c = w.dot(m_up); + if (c != 0) + { + //there is a component in walkdirection for vertical velocity + btVector3 upComponent = m_up * (sinf(SIMD_HALF_PI - acosf(c)) * m_walkDirection.length()); + m_walkDirection -= upComponent; + m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length(); + + if (c > 0.0f) + { + m_wasJumping = true; + m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin(); + } + } + } + else + m_verticalVelocity = 0.0f; +} + +btVector3 btKinematicCharacterController::getLinearVelocity() const +{ + return m_walkDirection + (m_verticalVelocity * m_up); +} + +void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld ) +{ + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + m_wasOnGround = false; + m_wasJumping = false; + m_walkDirection.setValue(0,0,0); + m_velocityTimeInterval = 0.0; + + //clear pair cache + btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache(); + while (cache->getOverlappingPairArray().size() > 0) + { + cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher()); + } } void btKinematicCharacterController::warp (const btVector3& origin) @@ -607,62 +705,99 @@ void btKinematicCharacterController::warp (const btVector3& origin) void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld) { - - int numPenetrationLoops = 0; - m_touchingContact = false; - while (recoverFromPenetration (collisionWorld)) - { - numPenetrationLoops++; - m_touchingContact = true; - if (numPenetrationLoops > 4) - { - //printf("character could not recover from penetration = %d\n", numPenetrationLoops); - break; - } - } - m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); m_targetPosition = m_currentPosition; -// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); - + m_currentOrientation = m_ghostObject->getWorldTransform().getRotation(); + m_targetOrientation = m_currentOrientation; +// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); } -#include - void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt) { // printf("playerStep(): "); // printf(" dt = %f", dt); + if (m_AngVel.length2() > 0.0f) + { + m_AngVel *= btPow(btScalar(1) - m_angularDamping, dt); + } + + // integrate for angular velocity + if (m_AngVel.length2() > 0.0f) + { + btTransform xform; + xform = m_ghostObject->getWorldTransform(); + + btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt); + + btQuaternion orn = rot * xform.getRotation(); + + xform.setRotation(orn); + m_ghostObject->setWorldTransform(xform); + + m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); + m_targetPosition = m_currentPosition; + m_currentOrientation = m_ghostObject->getWorldTransform().getRotation(); + m_targetOrientation = m_currentOrientation; + } + // quick check... - if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0 || m_walkDirection.fuzzyZero())) { + if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0)) { // printf("\n"); return; // no motion } m_wasOnGround = onGround(); + //btVector3 lvel = m_walkDirection; + //btScalar c = 0.0f; + + if (m_walkDirection.length2() > 0) + { + // apply damping + m_walkDirection *= btPow(btScalar(1) - m_linearDamping, dt); + } + + m_verticalVelocity *= btPow(btScalar(1) - m_linearDamping, dt); + // Update fall velocity. m_verticalVelocity -= m_gravity * dt; - if(m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed) + if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed) { m_verticalVelocity = m_jumpSpeed; } - if(m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed)) + if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed)) { m_verticalVelocity = -btFabs(m_fallSpeed); } m_verticalOffset = m_verticalVelocity * dt; - btTransform xform; - xform = m_ghostObject->getWorldTransform (); + xform = m_ghostObject->getWorldTransform(); // printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]); // printf("walkSpeed=%f\n",walkSpeed); - stepUp (collisionWorld); + stepUp(collisionWorld); + //todo: Experimenting with behavior of controller when it hits a ceiling.. + //bool hitUp = stepUp (collisionWorld); + //if (hitUp) + //{ + // m_verticalVelocity -= m_gravity * dt; + // if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed) + // { + // m_verticalVelocity = m_jumpSpeed; + // } + // if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed)) + // { + // m_verticalVelocity = -btFabs(m_fallSpeed); + // } + // m_verticalOffset = m_verticalVelocity * dt; + + // xform = m_ghostObject->getWorldTransform(); + //} + if (m_useWalkDirection) { stepForwardAndStrafe (collisionWorld, m_walkDirection); } else { @@ -682,10 +817,38 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo } stepDown (collisionWorld, dt); + //todo: Experimenting with max jump height + //if (m_wasJumping) + //{ + // btScalar ds = m_currentPosition[m_upAxis] - m_jumpPosition[m_upAxis]; + // if (ds > m_maxJumpHeight) + // { + // // substract the overshoot + // m_currentPosition[m_upAxis] -= ds - m_maxJumpHeight; + + // // max height was reached, so potential energy is at max + // // and kinematic energy is 0, thus velocity is 0. + // if (m_verticalVelocity > 0.0) + // m_verticalVelocity = 0.0; + // } + //} // printf("\n"); xform.setOrigin (m_currentPosition); m_ghostObject->setWorldTransform (xform); + + int numPenetrationLoops = 0; + m_touchingContact = false; + while (recoverFromPenetration(collisionWorld)) + { + numPenetrationLoops++; + m_touchingContact = true; + if (numPenetrationLoops > 4) + { + //printf("character could not recover from penetration = %d\n", numPenetrationLoops); + break; + } + } } void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed) @@ -696,6 +859,7 @@ void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed) void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed) { m_jumpSpeed = jumpSpeed; + m_SetjumpSpeed = m_jumpSpeed; } void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight) @@ -708,14 +872,16 @@ bool btKinematicCharacterController::canJump () const return onGround(); } -void btKinematicCharacterController::jump () +void btKinematicCharacterController::jump(const btVector3& v) { - if (!canJump()) - return; - + m_jumpSpeed = v.length2() == 0 ? m_SetjumpSpeed : v.length(); m_verticalVelocity = m_jumpSpeed; m_wasJumping = true; + m_jumpAxis = v.length2() == 0 ? m_up : v.normalized(); + + m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin(); + #if 0 currently no jumping. btTransform xform; @@ -727,14 +893,16 @@ void btKinematicCharacterController::jump () #endif } -void btKinematicCharacterController::setGravity(btScalar gravity) +void btKinematicCharacterController::setGravity(const btVector3& gravity) { - m_gravity = gravity; + if (gravity.length2() > 0) setUpVector(-gravity); + + m_gravity = gravity.length(); } -btScalar btKinematicCharacterController::getGravity() const +btVector3 btKinematicCharacterController::getGravity() const { - return m_gravity; + return -m_gravity * m_up; } void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians) @@ -748,11 +916,25 @@ btScalar btKinematicCharacterController::getMaxSlope() const return m_maxSlopeRadians; } +void btKinematicCharacterController::setMaxPenetrationDepth(btScalar d) +{ + m_maxPenetrationDepth = d; +} + +btScalar btKinematicCharacterController::getMaxPenetrationDepth() const +{ + return m_maxPenetrationDepth; +} + bool btKinematicCharacterController::onGround () const { - return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0; + return (fabs(m_verticalVelocity) < SIMD_EPSILON) && (fabs(m_verticalOffset) < SIMD_EPSILON); } +void btKinematicCharacterController::setStepHeight(btScalar h) +{ + m_stepHeight = h; +} btVector3* btKinematicCharacterController::getUpAxisDirections() { @@ -769,3 +951,49 @@ void btKinematicCharacterController::setUpInterpolate(bool value) { m_interpolateUp = value; } + +void btKinematicCharacterController::setUp(const btVector3& up) +{ + if (up.length2() > 0 && m_gravity > 0.0f) + { + setGravity(-m_gravity * up.normalized()); + return; + } + + setUpVector(up); +} + +void btKinematicCharacterController::setUpVector(const btVector3& up) +{ + if (m_up == up) + return; + + btVector3 u = m_up; + + if (up.length2() > 0) + m_up = up.normalized(); + else + m_up = btVector3(0.0, 0.0, 0.0); + + if (!m_ghostObject) return; + btQuaternion rot = getRotation(m_up, u); + + //set orientation with new up + btTransform xform; + xform = m_ghostObject->getWorldTransform(); + btQuaternion orn = rot.inverse() * xform.getRotation(); + xform.setRotation(orn); + m_ghostObject->setWorldTransform(xform); +} + +btQuaternion btKinematicCharacterController::getRotation(btVector3& v0, btVector3& v1) const +{ + if (v0.length2() == 0.0f || v1.length2() == 0.0f) + { + btQuaternion q; + return q; + } + + return shortestArcQuatNormalize2(v0, v1); +} + diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.h index add6f30a68..3d677e647e 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Character/btKinematicCharacterController.h @@ -43,10 +43,12 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo btPairCachingGhostObject* m_ghostObject; btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast + btScalar m_maxPenetrationDepth; btScalar m_verticalVelocity; btScalar m_verticalOffset; btScalar m_fallSpeed; btScalar m_jumpSpeed; + btScalar m_SetjumpSpeed; btScalar m_maxJumpHeight; btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) @@ -61,24 +63,34 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo ///this is the desired walk direction, set by the user btVector3 m_walkDirection; btVector3 m_normalizedDirection; + btVector3 m_AngVel; + + btVector3 m_jumpPosition; //some internal variables btVector3 m_currentPosition; btScalar m_currentStepOffset; btVector3 m_targetPosition; + btQuaternion m_currentOrientation; + btQuaternion m_targetOrientation; + ///keep track of the contact manifolds btManifoldArray m_manifoldArray; bool m_touchingContact; btVector3 m_touchingNormal; + btScalar m_linearDamping; + btScalar m_angularDamping; + bool m_wasOnGround; bool m_wasJumping; bool m_useGhostObjectSweepTest; bool m_useWalkDirection; btScalar m_velocityTimeInterval; - int m_upAxis; + btVector3 m_up; + btVector3 m_jumpAxis; static btVector3* getUpAxisDirections(); bool m_interpolateUp; @@ -94,11 +106,18 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove); void stepDown (btCollisionWorld* collisionWorld, btScalar dt); + + virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1); + + void setUpVector(const btVector3& up); + + btQuaternion getRotation(btVector3& v0, btVector3& v1) const; + public: BT_DECLARE_ALIGNED_ALLOCATOR(); - btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1); + btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up = btVector3(1.0,0.0,0.0)); ~btKinematicCharacterController (); @@ -112,14 +131,9 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo ///btActionInterface interface void debugDraw(btIDebugDraw* debugDrawer); - void setUpAxis (int axis) - { - if (axis < 0) - axis = 0; - if (axis > 2) - axis = 2; - m_upAxis = axis; - } + void setUp(const btVector3& up); + + const btVector3& getUp() { return m_up; } /// This should probably be called setPositionIncrementPerSimulatorStep. /// This is neither a direction nor a velocity, but the amount to @@ -136,27 +150,47 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval); + virtual void setAngularVelocity(const btVector3& velocity); + virtual const btVector3& getAngularVelocity() const; + + virtual void setLinearVelocity(const btVector3& velocity); + virtual btVector3 getLinearVelocity() const; + + void setLinearDamping(btScalar d) { m_linearDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); } + btScalar getLinearDamping() const { return m_linearDamping; } + void setAngularDamping(btScalar d) { m_angularDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); } + btScalar getAngularDamping() const { return m_angularDamping; } + void reset ( btCollisionWorld* collisionWorld ); void warp (const btVector3& origin); void preStep ( btCollisionWorld* collisionWorld); void playerStep ( btCollisionWorld* collisionWorld, btScalar dt); + void setStepHeight(btScalar h); + btScalar getStepHeight() const { return m_stepHeight; } void setFallSpeed (btScalar fallSpeed); + btScalar getFallSpeed() const { return m_fallSpeed; } void setJumpSpeed (btScalar jumpSpeed); + btScalar getJumpSpeed() const { return m_jumpSpeed; } void setMaxJumpHeight (btScalar maxJumpHeight); bool canJump () const; - void jump (); + void jump(const btVector3& v = btVector3()); + + void applyImpulse(const btVector3& v) { jump(v); } - void setGravity(btScalar gravity); - btScalar getGravity() const; + void setGravity(const btVector3& gravity); + btVector3 getGravity() const; /// The max slope determines the maximum angle that the controller can walk up. /// The slope angle is measured in radians. void setMaxSlope(btScalar slopeRadians); btScalar getMaxSlope() const; + void setMaxPenetrationDepth(btScalar d); + btScalar getMaxPenetrationDepth() const; + btPairCachingGhostObject* getGhostObject(); void setUseGhostSweepTest(bool useGhostObjectSweepTest) { diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index 4a058c3d31..09b7388b63 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -214,7 +214,7 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt } // m_swingCorrection is always positive or 0 info->m_lowerLimit[srow] = 0; - info->m_upperLimit[srow] = SIMD_INFINITY; + info->m_upperLimit[srow] = (m_bMotorEnabled && m_maxMotorImpulse >= 0.0f) ? m_maxMotorImpulse : SIMD_INFINITY; srow += info->rowskip; } } diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index 1735b524db..b7636180c3 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -170,6 +170,11 @@ ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint { m_angularOnly = angularOnly; } + + bool getAngularOnly() const + { + return m_angularOnly; + } void setLimit(int limitIndex,btScalar limitValue) { @@ -196,6 +201,33 @@ ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint }; } + btScalar getLimit(int limitIndex) const + { + switch (limitIndex) + { + case 3: + { + return m_twistSpan; + break; + } + case 4: + { + return m_swingSpan2; + break; + } + case 5: + { + return m_swingSpan1; + break; + } + default: + { + btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint"); + return 0.0; + } + }; + } + // setLimit(), a few notes: // _softness: // 0->1, recommend ~0.8->1. @@ -218,8 +250,8 @@ ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint m_relaxationFactor = _relaxationFactor; } - const btTransform& getAFrame() { return m_rbAFrame; }; - const btTransform& getBFrame() { return m_rbBFrame; }; + const btTransform& getAFrame() const { return m_rbAFrame; }; + const btTransform& getBFrame() const { return m_rbBFrame; }; inline int getSolveTwistLimit() { @@ -239,27 +271,43 @@ ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint void calcAngleInfo(); void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); - inline btScalar getSwingSpan1() + inline btScalar getSwingSpan1() const { return m_swingSpan1; } - inline btScalar getSwingSpan2() + inline btScalar getSwingSpan2() const { return m_swingSpan2; } - inline btScalar getTwistSpan() + inline btScalar getTwistSpan() const { return m_twistSpan; } - inline btScalar getTwistAngle() + inline btScalar getLimitSoftness() const + { + return m_limitSoftness; + } + inline btScalar getBiasFactor() const + { + return m_biasFactor; + } + inline btScalar getRelaxationFactor() const + { + return m_relaxationFactor; + } + inline btScalar getTwistAngle() const { return m_twistAngle; } bool isPastSwingLimit() { return m_solveSwingLimit; } + btScalar getDamping() const { return m_damping; } void setDamping(btScalar damping) { m_damping = damping; } void enableMotor(bool b) { m_bMotorEnabled = b; } + bool isMotorEnabled() const { return m_bMotorEnabled; } + btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; } + bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; } void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; } void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; } @@ -271,6 +319,7 @@ ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability) // note: don't forget to enableMotor() void setMotorTarget(const btQuaternion &q); + const btQuaternion& getMotorTarget() const { return m_qTarget; } // same as above, but q is the desired rotation of frameA wrt frameB in constraint space void setMotorTargetInConstraintSpace(const btQuaternion &q); @@ -297,6 +346,11 @@ ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint ///return the local value of parameter virtual btScalar getParam(int num, int axis = -1) const; + int getFlags() const + { + return m_flags; + } + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index a3a0fa6729..739b066fe9 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -58,7 +58,7 @@ struct btContactSolverInfoData int m_minimumSolverBatchSize; btScalar m_maxGyroscopicForce; btScalar m_singleAxisRollingFrictionThreshold; - + btScalar m_leastSquaresResidualThreshold; }; @@ -77,7 +77,7 @@ struct btContactSolverInfo : public btContactSolverInfoData m_maxErrorReduction = btScalar(20.); m_numIterations = 10; m_erp = btScalar(0.2); - m_erp2 = btScalar(0.8); + m_erp2 = btScalar(0.2); m_globalCfm = btScalar(0.); m_sor = btScalar(1.); m_splitImpulse = true; @@ -91,6 +91,7 @@ struct btContactSolverInfo : public btContactSolverInfoData m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows. + m_leastSquaresResidualThreshold = 0.f; } }; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index 431a524169..bea8629c32 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -111,14 +111,14 @@ class btRotationalLimitMotor //! Is limited - bool isLimited() + bool isLimited() const { if(m_loLimit > m_hiLimit) return false; return true; } //! Need apply correction - bool needApplyTorques() + bool needApplyTorques() const { if(m_currentLimit == 0 && m_enableMotor == false) return false; return true; @@ -207,11 +207,11 @@ class btTranslationalLimitMotor - limited means upper > lower - limitIndex: first 3 are linear, next 3 are angular */ - inline bool isLimited(int limitIndex) + inline bool isLimited(int limitIndex) const { return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); } - inline bool needApplyForce(int limitIndex) + inline bool needApplyForce(int limitIndex) const { if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; return true; @@ -457,7 +457,7 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint m_linearLimits.m_lowerLimit = linearLower; } - void getLinearLowerLimit(btVector3& linearLower) + void getLinearLowerLimit(btVector3& linearLower) const { linearLower = m_linearLimits.m_lowerLimit; } @@ -467,7 +467,7 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint m_linearLimits.m_upperLimit = linearUpper; } - void getLinearUpperLimit(btVector3& linearUpper) + void getLinearUpperLimit(btVector3& linearUpper) const { linearUpper = m_linearLimits.m_upperLimit; } @@ -478,7 +478,7 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]); } - void getAngularLowerLimit(btVector3& angularLower) + void getAngularLowerLimit(btVector3& angularLower) const { for(int i = 0; i < 3; i++) angularLower[i] = m_angularLimits[i].m_loLimit; @@ -490,7 +490,7 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]); } - void getAngularUpperLimit(btVector3& angularUpper) + void getAngularUpperLimit(btVector3& angularUpper) const { for(int i = 0; i < 3; i++) angularUpper[i] = m_angularLimits[i].m_hiLimit; @@ -532,7 +532,7 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint - limited means upper > lower - limitIndex: first 3 are linear, next 3 are angular */ - bool isLimited(int limitIndex) + bool isLimited(int limitIndex) const { if(limitIndex<3) { @@ -549,8 +549,11 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false); // access for UseFrameOffset - bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + bool getUseFrameOffset() const { return m_useOffsetForConstraintFrame; } void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + bool getUseLinearReferenceFrameA() const { return m_useLinearReferenceFrameA; } + void setUseLinearReferenceFrameA(bool linearReferenceFrameA) { m_useLinearReferenceFrameA = linearReferenceFrameA; } ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. @@ -560,6 +563,10 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint void setAxis( const btVector3& axis1, const btVector3& axis2); + virtual int getFlags() const + { + return m_flags; + } virtual int calculateSerializeBufferSize() const; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h index 738d52ce86..57b4e1983a 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h @@ -319,14 +319,6 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpring2Constraint : public btTypedConstr const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false); - static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); - static bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz); - public: BT_DECLARE_ALIGNED_ALLOCATOR(); @@ -489,6 +481,14 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpring2Constraint : public btTypedConstr //If no axis is provided, it uses the default axis for this constraint. virtual void setParam(int num, btScalar value, int axis = -1); virtual btScalar getParam(int num, int axis = -1) const; + + static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); + static bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); + static bool matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz); + static bool matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz); + static bool matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz); + static bool matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz); + static bool matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz); }; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h index 1b2e0f62ca..dac59c6889 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h @@ -63,6 +63,26 @@ ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpringConstraint : public btGeneric6DofC void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF void setEquilibriumPoint(int index, btScalar val); + bool isSpringEnabled(int index) const + { + return m_springEnabled[index]; + } + + btScalar getStiffness(int index) const + { + return m_springStiffness[index]; + } + + btScalar getDamping(int index) const + { + return m_springDamping[index]; + } + + btScalar getEquilibriumPoint(int index) const + { + return m_equilibriumPoint[index]; + } + virtual void setAxis( const btVector3& axis1, const btVector3& axis2); virtual void getInfo2 (btConstraintInfo2* info); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 9cdb941b61..f26e72105b 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -177,6 +177,7 @@ ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint // maintain a given angular target. void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; } void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; } + void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; } void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B. void setMotorTarget(btScalar targetAngle, btScalar dt); @@ -193,6 +194,33 @@ ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint m_relaxationFactor = _relaxationFactor; #endif } + + btScalar getLimitSoftness() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getSoftness(); +#else + return m_limitSoftness; +#endif + } + + btScalar getLimitBiasFactor() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getBiasFactor(); +#else + return m_biasFactor; +#endif + } + + btScalar getLimitRelaxationFactor() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getRelaxationFactor(); +#else + return m_relaxationFactor; +#endif + } void setAxis(btVector3& axisInA) { @@ -297,13 +325,20 @@ ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint // access for UseFrameOffset bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } - + // access for UseReferenceFrameA + bool getUseReferenceFrameA() const { return m_useReferenceFrameA; } + void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; } ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter virtual btScalar getParam(int num, int axis = -1) const; + + virtual int getFlags() const + { + return m_flags; + } virtual int calculateSerializeBufferSize() const; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index 9121894949..8fa03d719d 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -116,6 +116,11 @@ ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter virtual btScalar getParam(int num, int axis = -1) const; + + virtual int getFlags() const + { + return m_flags; + } virtual int calculateSerializeBufferSize() const; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index c5b1beb09e..14565f511c 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -41,7 +41,7 @@ int gNumSplitImpulseRecoveries = 0; #include "BulletDynamics/Dynamics/btRigidBody.h" - +//#define VERBOSE_RESIDUAL_PRINTF 1 ///This is the scalar reference implementation of solving a single constraint row, the innerloop of the Projected Gauss Seidel/Sequential Impulse constraint solver ///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check. static btSimdScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c) @@ -300,15 +300,17 @@ btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowe } -void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly( +btScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly( btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c) { + btScalar deltaImpulse = 0.f; + if (c.m_rhsPenetration) { gNumSplitImpulseRecoveries++; - btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm; + deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm; const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity()); const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity()); @@ -327,13 +329,14 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri body1.internalApplyPushImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); body2.internalApplyPushImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); } + return deltaImpulse; } - void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +btSimdScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) { #ifdef USE_SIMD if (!c.m_rhsPenetration) - return; + return 0.f; gNumSplitImpulseRecoveries++; @@ -359,8 +362,9 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); body2.internalGetPushVelocity().mVec128 = _mm_add_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); + return deltaImpulse; #else - resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c); + return resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c); #endif } @@ -630,8 +634,8 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(c } -void btSequentialImpulseConstraintSolver::setupRollingFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB, - btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, +void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB, + btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2, btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) @@ -650,8 +654,8 @@ void btSequentialImpulseConstraintSolver::setupRollingFrictionConstraint( btSolv solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_friction = cp.m_combinedRollingFriction; - solverConstraint.m_originalContactPoint = 0; + solverConstraint.m_friction = combinedTorsionalFriction; + solverConstraint.m_originalContactPoint = 0; solverConstraint.m_appliedImpulse = 0.f; solverConstraint.m_appliedPushImpulse = 0.f; @@ -708,11 +712,11 @@ void btSequentialImpulseConstraintSolver::setupRollingFrictionConstraint( btSolv -btSolverConstraint& btSequentialImpulseConstraintSolver::addRollingFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) { btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing(); solverConstraint.m_frictionIndex = frictionIndex; - setupRollingFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, + setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction,rel_pos1, rel_pos2, colObj0, colObj1, relaxation, desiredVelocity, cfmSlip); return solverConstraint; } @@ -720,8 +724,67 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addRollingFrictionConst int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep) { +#if BT_THREADSAFE + int solverBodyId = -1; + if ( !body.isStaticOrKinematicObject() ) + { + // dynamic body + // Dynamic bodies can only be in one island, so it's safe to write to the companionId + solverBodyId = body.getCompanionId(); + if ( solverBodyId < 0 ) + { + if ( btRigidBody* rb = btRigidBody::upcast( &body ) ) + { + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody( &solverBody, &body, timeStep ); + body.setCompanionId( solverBodyId ); + } + } + } + else if (body.isKinematicObject()) + { + // + // NOTE: must test for kinematic before static because some kinematic objects also + // identify as "static" + // + // Kinematic bodies can be in multiple islands at once, so it is a + // race condition to write to them, so we use an alternate method + // to record the solverBodyId + int uniqueId = body.getWorldArrayIndex(); + const int INVALID_SOLVER_BODY_ID = -1; + if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size()) + { + m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID); + } + solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ]; + // if no table entry yet, + if ( solverBodyId == INVALID_SOLVER_BODY_ID ) + { + // create a table entry for this body + btRigidBody* rb = btRigidBody::upcast( &body ); + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody( &solverBody, &body, timeStep ); + m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId; + } + } + else + { + // all fixed bodies (inf mass) get mapped to a single solver id + if ( m_fixedBodyId < 0 ) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody( &fixedBody, 0, timeStep ); + } + solverBodyId = m_fixedBodyId; + } + btAssert( solverBodyId < m_tmpSolverBodyPool.size() ); + return solverBodyId; +#else // BT_THREADSAFE - int solverBodyIdA = -1; + int solverBodyIdA = -1; if (body.getCompanionId() >= 0) { @@ -753,6 +816,7 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& } return solverBodyIdA; +#endif // BT_THREADSAFE } #include @@ -779,7 +843,37 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); - relaxation = 1.f; + relaxation = infoGlobal.m_sor; + btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep; + + //cfm = 1 / ( dt * kp + kd ) + //erp = dt * kp / ( dt * kp + kd ) + + btScalar cfm = infoGlobal.m_globalCfm; + btScalar erp = infoGlobal.m_erp2; + + if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)) + { + if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) + cfm = cp.m_contactCFM; + if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP) + erp = cp.m_contactERP; + } else + { + if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING) + { + btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 ); + if (denom < SIMD_EPSILON) + { + denom = SIMD_EPSILON; + } + cfm = btScalar(1) / denom; + erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom; + } + } + + cfm *= invTimeStep; + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); @@ -806,7 +900,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra } #endif //COMPUTE_IMPULSE_DENOM - btScalar denom = relaxation/(denom0+denom1); + btScalar denom = relaxation/(denom0+denom1+cfm); solverConstraint.m_jacDiagABInv = denom; } @@ -888,20 +982,16 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra btScalar velocityError = restitution - rel_vel;// * damping; - btScalar erp = infoGlobal.m_erp2; - if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) - { - erp = infoGlobal.m_erp; - } - + if (penetration>0) { positionalError = 0; - velocityError -= penetration / infoGlobal.m_timeStep; + velocityError -= penetration *invTimeStep; } else { - positionalError = -penetration * erp/infoGlobal.m_timeStep; + positionalError = -penetration * erp*invTimeStep; + } btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; @@ -919,7 +1009,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra solverConstraint.m_rhs = velocityImpulse; solverConstraint.m_rhsPenetration = penetrationImpulse; } - solverConstraint.m_cfm = 0.f; + solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv; solverConstraint.m_lowerLimit = 0; solverConstraint.m_upperLimit = 1e10f; } @@ -1014,8 +1104,6 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m int frictionIndex = m_tmpSolverContactConstraintPool.size(); btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing(); - btRigidBody* rb0 = btRigidBody::upcast(colObj0); - btRigidBody* rb1 = btRigidBody::upcast(colObj1); solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; @@ -1027,9 +1115,9 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); - btVector3 vel1;// = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); - btVector3 vel2;// = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); - + btVector3 vel1; + btVector3 vel2; + solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1); solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 ); @@ -1040,45 +1128,31 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m -// const btVector3& pos1 = cp.getPositionWorldOnA(); -// const btVector3& pos2 = cp.getPositionWorldOnB(); /////setup the friction constraints solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size(); - btVector3 angVelA(0,0,0),angVelB(0,0,0); - if (rb0) - angVelA = rb0->getAngularVelocity(); - if (rb1) - angVelB = rb1->getAngularVelocity(); - btVector3 relAngVel = angVelB-angVelA; - if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0)) { - //only a single rollingFriction per manifold - rollingFriction--; - if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold) + { - relAngVel.normalize(); - applyAnisotropicFriction(colObj0,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj1,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - if (relAngVel.length()>0.001) - addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - - } else - { - addRollingFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addTorsionalFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,cp.m_combinedSpinningFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation); btVector3 axis0,axis1; btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1); + axis0.normalize(); + axis1.normalize(); + applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); if (axis0.length()>0.001) - addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addTorsionalFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp, + cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation); if (axis1.length()>0.001) - addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addTorsionalFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp, + cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation); } } @@ -1098,7 +1172,7 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) ///this will give a conveyor belt effect /// - if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED)) { cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); @@ -1136,16 +1210,16 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) { - cp.m_lateralFrictionInitialized = true; + cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; } } } else { - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_frictionCFM); if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_frictionCFM); } setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); @@ -1253,7 +1327,9 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol { bodies[i]->setCompanionId(-1); } - +#if BT_THREADSAFE + m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 ); +#endif // BT_THREADSAFE m_tmpSolverBodyPool.reserve(numBodies+1); m_tmpSolverBodyPool.resize(0); @@ -1532,6 +1608,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/) { + btScalar leastSquaresResidual = 0.f; int numNonContactPool = m_tmpSolverNonContactConstraintPool.size(); int numConstraintPool = m_tmpSolverContactConstraintPool.size(); @@ -1576,7 +1653,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration { btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]]; if (iteration < constraint.m_overrideNumSolverIterations) - resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); + { + btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); + leastSquaresResidual += residual*residual; + } } if (iteration< infoGlobal.m_numIterations) @@ -1605,7 +1685,9 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration { const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]]; - resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + btScalar residual = resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + leastSquaresResidual += residual*residual; + totalImpulse = solveManifold.m_appliedImpulse; } bool applyFriction = true; @@ -1620,7 +1702,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + leastSquaresResidual += residual*residual; } } @@ -1634,7 +1717,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + leastSquaresResidual += residual*residual; } } } @@ -1650,8 +1734,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration for (j=0;j=(infoGlobal.m_numIterations-1)) + { +#ifdef VERBOSE_RESIDUAL_PRINTF + printf("residual = %f at iteration #%d\n",leastSquaresResidual,iteration); +#endif + break; + } } } else { for ( iteration = 0;iteration=(infoGlobal.m_numIterations-1)) + { +#ifdef VERBOSE_RESIDUAL_PRINTF + printf("residual = %f at iteration #%d\n",leastSquaresResidual,iteration); +#endif + break; } } } @@ -1819,7 +1929,15 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations( for ( int iteration = 0 ; iteration< maxIterations ; iteration++) //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--) { - solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + m_leastSquaresResidual = solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + + if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration>= (maxIterations-1))) + { +#ifdef VERBOSE_RESIDUAL_PRINTF + printf("residual = %f at iteration #%d\n",m_leastSquaresResidual,iteration); +#endif + break; + } } } diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index a602918098..0dd31d142e 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -45,22 +45,32 @@ ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstr btAlignedObjectArray m_tmpConstraintSizesPool; int m_maxOverrideNumSolverIterations; int m_fixedBodyId; + // When running solvers on multiple threads, a race condition exists for Kinematic objects that + // participate in more than one solver. + // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body + // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island + // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once. + // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body + // index in this solver-local table, indexed by the uniqueId of the body. + btAlignedObjectArray m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric; btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit; + btScalar m_leastSquaresResidual; + void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.); - void setupRollingFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, - btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, + void setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, + btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2, btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.); btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.); - btSolverConstraint& addRollingFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f); + btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar torsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f); void setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, @@ -82,11 +92,11 @@ ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstr void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); - void resolveSplitPenetrationSIMD( + btSimdScalar resolveSplitPenetrationSIMD( btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint); - void resolveSplitPenetrationImpulseCacheFriendly( + btScalar resolveSplitPenetrationImpulseCacheFriendly( btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h index 57ebb47d8e..1957f08a96 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -25,6 +25,8 @@ April 04, 2008 #ifndef BT_SLIDER_CONSTRAINT_H #define BT_SLIDER_CONSTRAINT_H +#include "LinearMath/btScalar.h"//for BT_USE_DOUBLE_PRECISION + #ifdef BT_USE_DOUBLE_PRECISION #define btSliderConstraintData2 btSliderConstraintDoubleData #define btSliderConstraintDataName "btSliderConstraintDoubleData" @@ -280,6 +282,11 @@ ATTRIBUTE_ALIGNED16(class) btSliderConstraint : public btTypedConstraint virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter virtual btScalar getParam(int num, int axis = -1) const; + + virtual int getFlags() const + { + return m_flags; + } virtual int calculateSerializeBufferSize() const; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index ea44ae4b45..8a2a2d1ae7 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -66,6 +66,7 @@ enum btConstraintParams ATTRIBUTE_ALIGNED16(struct) btJointFeedback { + BT_DECLARE_ALIGNED_ALLOCATOR(); btVector3 m_appliedForceBodyA; btVector3 m_appliedTorqueBodyA; btVector3 m_appliedForceBodyB; @@ -144,11 +145,6 @@ ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject // lo and hi limits for variables (set to -/+ infinity on entry). btScalar *m_lowerLimit,*m_upperLimit; - // findex vector for variables. see the LCP solver interface for a - // description of what this does. this is set to -1 on entry. - // note that the returned indexes are relative to the first index of - // the constraint. - int *findex; // number of solver iterations int m_numIterations; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 0c936d6fbe..8610280f3b 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -462,6 +462,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, synchronizeMotionStates(); } + clearForces(); + #ifndef BT_NO_PROFILE CProfileManager::Increment_Frame_Counter(); #endif //BT_NO_PROFILE @@ -537,7 +539,7 @@ btVector3 btDiscreteDynamicsWorld::getGravity () const return m_gravity; } -void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask) { btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask); } @@ -576,14 +578,14 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body) } bool isDynamic = !(body->isStaticObject() || body->isKinematicObject()); - short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter); - short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + int collisionFilterGroup = isDynamic? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter); + int collisionFilterMask = isDynamic? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); addCollisionObject(body,collisionFilterGroup,collisionFilterMask); } } -void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask) { if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) { @@ -876,25 +878,12 @@ class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConve int gNumClampedCcdMotions=0; -void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep) +void btDiscreteDynamicsWorld::createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep) { - BT_PROFILE("createPredictiveContacts"); - - { - BT_PROFILE("release predictive contact manifolds"); - - for (int i=0;im_dispatcher1->releaseManifold(manifold); - } - m_predictiveManifolds.clear(); - } - btTransform predictedTrans; - for ( int i=0;isetHitFraction(1.f); if (body->isActive() && (!body->isStaticOrKinematicObject())) @@ -951,7 +940,9 @@ void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep) btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject); + btMutexLock( &m_predictiveManifoldsMutex ); m_predictiveManifolds.push_back(manifold); + btMutexUnlock( &m_predictiveManifoldsMutex ); btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec; btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB; @@ -972,13 +963,35 @@ void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep) } } } -void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) + +void btDiscreteDynamicsWorld::releasePredictiveContacts() +{ + BT_PROFILE( "release predictive contact manifolds" ); + + for ( int i = 0; i < m_predictiveManifolds.size(); i++ ) + { + btPersistentManifold* manifold = m_predictiveManifolds[ i ]; + this->m_dispatcher1->releaseManifold( manifold ); + } + m_predictiveManifolds.clear(); +} + +void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep) +{ + BT_PROFILE("createPredictiveContacts"); + releasePredictiveContacts(); + if (m_nonStaticRigidBodies.size() > 0) + { + createPredictiveContactsInternal( &m_nonStaticRigidBodies[ 0 ], m_nonStaticRigidBodies.size(), timeStep ); + } +} + +void btDiscreteDynamicsWorld::integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ) { - BT_PROFILE("integrateTransforms"); btTransform predictedTrans; - for ( int i=0;isetHitFraction(1.f); if (body->isActive() && (!body->isStaticOrKinematicObject())) @@ -1078,7 +1091,17 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) } - ///this should probably be switched on by default, but it is not well tested yet +} + +void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + BT_PROFILE("integrateTransforms"); + if (m_nonStaticRigidBodies.size() > 0) + { + integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep); + } + + ///this should probably be switched on by default, but it is not well tested yet if (m_applySpeculativeContactRestitution) { BT_PROFILE("apply speculative contact restitution"); @@ -1112,14 +1135,12 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) } } } - } - void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { BT_PROFILE("predictUnconstraintMotion"); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index dd3d1c3660..b0d19f48a3 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -30,6 +30,7 @@ class btIDebugDraw; struct InplaceSolverIslandCallback; #include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btThreads.h" ///btDiscreteDynamicsWorld provides discrete rigid body simulation @@ -68,9 +69,11 @@ ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld bool m_latencyMotionStateInterpolation; btAlignedObjectArray m_predictiveManifolds; + btSpinMutex m_predictiveManifoldsMutex; // used to synchronize threads creating predictive contacts virtual void predictUnconstraintMotion(btScalar timeStep); + void integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel virtual void integrateTransforms(btScalar timeStep); virtual void calculateSimulationIslands(); @@ -85,7 +88,9 @@ ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld virtual void internalSingleStepSimulation( btScalar timeStep); - void createPredictiveContacts(btScalar timeStep); + void releasePredictiveContacts(); + void createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel + virtual void createPredictiveContacts(btScalar timeStep); virtual void saveKinematicState(btScalar timeStep); @@ -139,11 +144,11 @@ ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld virtual btVector3 getGravity () const; - virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::StaticFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); virtual void addRigidBody(btRigidBody* body); - virtual void addRigidBody(btRigidBody* body, short group, short mask); + virtual void addRigidBody(btRigidBody* body, int group, int mask); virtual void removeRigidBody(btRigidBody* body); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp new file mode 100644 index 0000000000..5e51a994c1 --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp @@ -0,0 +1,162 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without 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. +*/ + + +#include "btDiscreteDynamicsWorldMt.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "btSimulationIslandManagerMt.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btQuickprof.h" + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + + +#include "BulletDynamics/Dynamics/btActionInterface.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btMotionState.h" + +#include "LinearMath/btSerializer.h" + + +struct InplaceSolverIslandCallbackMt : public btSimulationIslandManagerMt::IslandCallback +{ + btContactSolverInfo* m_solverInfo; + btConstraintSolver* m_solver; + btIDebugDraw* m_debugDrawer; + btDispatcher* m_dispatcher; + + InplaceSolverIslandCallbackMt( + btConstraintSolver* solver, + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) + :m_solverInfo(NULL), + m_solver(solver), + m_debugDrawer(NULL), + m_dispatcher(dispatcher) + { + + } + + InplaceSolverIslandCallbackMt& operator=(InplaceSolverIslandCallbackMt& other) + { + btAssert(0); + (void)other; + return *this; + } + + SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btIDebugDraw* debugDrawer) + { + btAssert(solverInfo); + m_solverInfo = solverInfo; + m_debugDrawer = debugDrawer; + } + + + virtual void processIsland( btCollisionObject** bodies, + int numBodies, + btPersistentManifold** manifolds, + int numManifolds, + btTypedConstraint** constraints, + int numConstraints, + int islandId + ) + { + m_solver->solveGroup( bodies, + numBodies, + manifolds, + numManifolds, + constraints, + numConstraints, + *m_solverInfo, + m_debugDrawer, + m_dispatcher + ); + } + +}; + + + +btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) +: btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ + if (m_ownsIslandManager) + { + m_islandManager->~btSimulationIslandManager(); + btAlignedFree( m_islandManager); + } + { + void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallbackMt),16); + m_solverIslandCallbackMt = new (mem) InplaceSolverIslandCallbackMt (m_constraintSolver, 0, dispatcher); + } + { + void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16); + btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt(); + m_islandManager = im; + im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize ); + } +} + + +btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt() +{ + if (m_solverIslandCallbackMt) + { + m_solverIslandCallbackMt->~InplaceSolverIslandCallbackMt(); + btAlignedFree(m_solverIslandCallbackMt); + } + if (m_ownsConstraintSolver) + { + m_constraintSolver->~btConstraintSolver(); + btAlignedFree(m_constraintSolver); + } +} + + +void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo) +{ + BT_PROFILE("solveConstraints"); + + m_solverIslandCallbackMt->setup(&solverInfo, getDebugDrawer()); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); + + /// solve all the constraints for this island + btSimulationIslandManagerMt* im = static_cast(m_islandManager); + im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, m_solverIslandCallbackMt ); + + m_constraintSolver->allSolved(solverInfo, m_debugDrawer); +} + + diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h new file mode 100644 index 0000000000..b28371b517 --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without 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 BT_DISCRETE_DYNAMICS_WORLD_MT_H +#define BT_DISCRETE_DYNAMICS_WORLD_MT_H + +#include "btDiscreteDynamicsWorld.h" + +struct InplaceSolverIslandCallbackMt; + +/// +/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support +/// solving simulation islands on multiple threads. +/// +ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld +{ +protected: + InplaceSolverIslandCallbackMt* m_solverIslandCallbackMt; + + virtual void solveConstraints(btContactSolverInfo& solverInfo); + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + virtual ~btDiscreteDynamicsWorldMt(); +}; + +#endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 35dd1400fe..a9ed1978f5 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -34,7 +34,8 @@ enum btDynamicsWorldType BT_DISCRETE_DYNAMICS_WORLD=2, BT_CONTINUOUS_DYNAMICS_WORLD=3, BT_SOFT_RIGID_DYNAMICS_WORLD=4, - BT_GPU_DYNAMICS_WORLD=5 + BT_GPU_DYNAMICS_WORLD=5, + BT_SOFT_MULTIBODY_DYNAMICS_WORLD=6 }; ///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. @@ -88,7 +89,7 @@ class btDynamicsWorld : public btCollisionWorld virtual void addRigidBody(btRigidBody* body) = 0; - virtual void addRigidBody(btRigidBody* body, short group, short mask) = 0; + virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0; virtual void removeRigidBody(btRigidBody* body) = 0; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp index 8bc3c1ca52..9402a658ca 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -79,6 +79,8 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& //moved to btCollisionObject m_friction = constructionInfo.m_friction; m_rollingFriction = constructionInfo.m_rollingFriction; + m_spinningFriction = constructionInfo.m_spinningFriction; + m_restitution = constructionInfo.m_restitution; setCollisionShape( constructionInfo.m_collisionShape ); @@ -303,13 +305,6 @@ btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForc return gf; } -void btSetCrossMatrixMinus(btMatrix3x3& res, const btVector3& a) -{ - const btScalar a_0 = a[0], a_1 = a[1], a_2 = a[2]; - res.setValue(0, +a_2, -a_1, - -a_2, 0, +a_0, - +a_1, -a_0, 0); -} btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const { diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.h index 1d177db802..372245031b 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btRigidBody.h @@ -135,6 +135,8 @@ class btRigidBody : public btCollisionObject ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever. ///See Bullet/Demos/RollingFrictionDemo for usage btScalar m_rollingFriction; + btScalar m_spinningFriction;//torsional friction around contact normal + ///best simulation results using zero restitution. btScalar m_restitution; @@ -158,6 +160,7 @@ class btRigidBody : public btCollisionObject m_angularDamping(btScalar(0.)), m_friction(btScalar(0.5)), m_rollingFriction(btScalar(0)), + m_spinningFriction(btScalar(0)), m_restitution(btScalar(0.)), m_linearSleepingThreshold(btScalar(0.8)), m_angularSleepingThreshold(btScalar(1.f)), diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 35dd38840f..6f63b87c80 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -155,7 +155,7 @@ void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body) } } -void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask) { body->setGravity(m_gravity); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h index d48d2e39c4..44b7e7fb34 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -56,7 +56,7 @@ class btSimpleDynamicsWorld : public btDynamicsWorld virtual void addRigidBody(btRigidBody* body); - virtual void addRigidBody(btRigidBody* body, short group, short mask); + virtual void addRigidBody(btRigidBody* body, int group, int mask); virtual void removeRigidBody(btRigidBody* body); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp new file mode 100644 index 0000000000..ad63b6ee0a --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp @@ -0,0 +1,641 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without 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. +*/ + + +#include "LinearMath/btScalar.h" +#include "btSimulationIslandManagerMt.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + +//#include +#include "LinearMath/btQuickprof.h" + + +SIMD_FORCE_INLINE int calcBatchCost( int bodies, int manifolds, int constraints ) +{ + // rough estimate of the cost of a batch, used for merging + int batchCost = bodies + 8 * manifolds + 4 * constraints; + return batchCost; +} + + +SIMD_FORCE_INLINE int calcBatchCost( const btSimulationIslandManagerMt::Island* island ) +{ + return calcBatchCost( island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size() ); +} + + +btSimulationIslandManagerMt::btSimulationIslandManagerMt() +{ + m_minimumSolverBatchSize = calcBatchCost(0, 128, 0); + m_batchIslandMinBodyCount = 32; + m_islandDispatch = defaultIslandDispatch; + m_batchIsland = NULL; +} + + +btSimulationIslandManagerMt::~btSimulationIslandManagerMt() +{ + for ( int i = 0; i < m_allocatedIslands.size(); ++i ) + { + delete m_allocatedIslands[ i ]; + } + m_allocatedIslands.resize( 0 ); + m_activeIslands.resize( 0 ); + m_freeIslands.resize( 0 ); +} + + +inline int getIslandId(const btPersistentManifold* lhs) +{ + const btCollisionObject* rcolObj0 = static_cast(lhs->getBody0()); + const btCollisionObject* rcolObj1 = static_cast(lhs->getBody1()); + int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag(); + return islandId; +} + + +SIMD_FORCE_INLINE int btGetConstraintIslandId( const btTypedConstraint* lhs ) +{ + const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); + const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); + int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag(); + return islandId; +} + +/// function object that routes calls to operator< +class IslandBatchSizeSortPredicate +{ +public: + bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const + { + int lCost = calcBatchCost( lhs ); + int rCost = calcBatchCost( rhs ); + return lCost > rCost; + } +}; + + +class IslandBodyCapacitySortPredicate +{ +public: + bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const + { + return lhs->bodyArray.capacity() > rhs->bodyArray.capacity(); + } +}; + + +void btSimulationIslandManagerMt::Island::append( const Island& other ) +{ + // append bodies + for ( int i = 0; i < other.bodyArray.size(); ++i ) + { + bodyArray.push_back( other.bodyArray[ i ] ); + } + // append manifolds + for ( int i = 0; i < other.manifoldArray.size(); ++i ) + { + manifoldArray.push_back( other.manifoldArray[ i ] ); + } + // append constraints + for ( int i = 0; i < other.constraintArray.size(); ++i ) + { + constraintArray.push_back( other.constraintArray[ i ] ); + } +} + + +bool btIsBodyInIsland( const btSimulationIslandManagerMt::Island& island, const btCollisionObject* obj ) +{ + for ( int i = 0; i < island.bodyArray.size(); ++i ) + { + if ( island.bodyArray[ i ] == obj ) + { + return true; + } + } + return false; +} + + +void btSimulationIslandManagerMt::initIslandPools() +{ + // reset island pools + int numElem = getUnionFind().getNumElements(); + m_lookupIslandFromId.resize( numElem ); + for ( int i = 0; i < m_lookupIslandFromId.size(); ++i ) + { + m_lookupIslandFromId[ i ] = NULL; + } + m_activeIslands.resize( 0 ); + m_freeIslands.resize( 0 ); + // check whether allocated islands are sorted by body capacity (largest to smallest) + int lastCapacity = 0; + bool isSorted = true; + for ( int i = 0; i < m_allocatedIslands.size(); ++i ) + { + Island* island = m_allocatedIslands[ i ]; + int cap = island->bodyArray.capacity(); + if ( cap > lastCapacity ) + { + isSorted = false; + break; + } + lastCapacity = cap; + } + if ( !isSorted ) + { + m_allocatedIslands.quickSort( IslandBodyCapacitySortPredicate() ); + } + + m_batchIsland = NULL; + // mark all islands free (but avoid deallocation) + for ( int i = 0; i < m_allocatedIslands.size(); ++i ) + { + Island* island = m_allocatedIslands[ i ]; + island->bodyArray.resize( 0 ); + island->manifoldArray.resize( 0 ); + island->constraintArray.resize( 0 ); + island->id = -1; + island->isSleeping = true; + m_freeIslands.push_back( island ); + } +} + + +btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland( int id ) +{ + Island* island = m_lookupIslandFromId[ id ]; + if ( island == NULL ) + { + // search for existing island + for ( int i = 0; i < m_activeIslands.size(); ++i ) + { + if ( m_activeIslands[ i ]->id == id ) + { + island = m_activeIslands[ i ]; + break; + } + } + m_lookupIslandFromId[ id ] = island; + } + return island; +} + + +btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland( int id, int numBodies ) +{ + Island* island = NULL; + int allocSize = numBodies; + if ( numBodies < m_batchIslandMinBodyCount ) + { + if ( m_batchIsland ) + { + island = m_batchIsland; + m_lookupIslandFromId[ id ] = island; + // if we've made a large enough batch, + if ( island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount ) + { + // next time start a new batch + m_batchIsland = NULL; + } + return island; + } + else + { + // need to allocate a batch island + allocSize = m_batchIslandMinBodyCount * 2; + } + } + btAlignedObjectArray& freeIslands = m_freeIslands; + + // search for free island + if ( freeIslands.size() > 0 ) + { + // try to reuse a previously allocated island + int iFound = freeIslands.size(); + // linear search for smallest island that can hold our bodies + for ( int i = freeIslands.size() - 1; i >= 0; --i ) + { + if ( freeIslands[ i ]->bodyArray.capacity() >= allocSize ) + { + iFound = i; + island = freeIslands[ i ]; + island->id = id; + break; + } + } + // if found, shrink array while maintaining ordering + if ( island ) + { + int iDest = iFound; + int iSrc = iDest + 1; + while ( iSrc < freeIslands.size() ) + { + freeIslands[ iDest++ ] = freeIslands[ iSrc++ ]; + } + freeIslands.pop_back(); + } + } + if ( island == NULL ) + { + // no free island found, allocate + island = new Island(); // TODO: change this to use the pool allocator + island->id = id; + island->bodyArray.reserve( allocSize ); + m_allocatedIslands.push_back( island ); + } + m_lookupIslandFromId[ id ] = island; + if ( numBodies < m_batchIslandMinBodyCount ) + { + m_batchIsland = island; + } + m_activeIslands.push_back( island ); + return island; +} + + +void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld ) +{ + + BT_PROFILE("islandUnionFindAndQuickSort"); + + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + + //we are going to sort the unionfind array, and store the element id in the size + //afterwards, we clean unionfind, to make sure no-one uses it anymore + + getUnionFind().sortIslands(); + int numElem = getUnionFind().getNumElements(); + + int endIslandIndex=1; + int startIslandIndex; + + //update the sleeping state for bodies, if all are sleeping + for ( startIslandIndex=0;startIslandIndexgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + if (colObj0->getIslandTag() == islandId) + { + if (colObj0->getActivationState()== ACTIVE_TAG) + { + allSleeping = false; + } + if (colObj0->getActivationState()== DISABLE_DEACTIVATION) + { + allSleeping = false; + } + } + } + + if (allSleeping) + { + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + colObj0->setActivationState( ISLAND_SLEEPING ); + } + } + } else + { + + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + if ( colObj0->getActivationState() == ISLAND_SLEEPING) + { + colObj0->setActivationState( WANTS_DEACTIVATION); + colObj0->setDeactivationTime(0.f); + } + } + } + } + } +} + + +void btSimulationIslandManagerMt::addBodiesToIslands( btCollisionWorld* collisionWorld ) +{ + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + int endIslandIndex = 1; + int startIslandIndex; + int numElem = getUnionFind().getNumElements(); + + // create explicit islands and add bodies to each + for ( startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex ) + { + int islandId = getUnionFind().getElement( startIslandIndex ).m_id; + + // find end index + for ( endIslandIndex = startIslandIndex; ( endIslandIndex < numElem ) && ( getUnionFind().getElement( endIslandIndex ).m_id == islandId ); endIslandIndex++ ) + { + } + // check if island is sleeping + bool islandSleeping = true; + for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ ) + { + int i = getUnionFind().getElement( iElem ).m_sz; + btCollisionObject* colObj = collisionObjects[ i ]; + if ( colObj->isActive() ) + { + islandSleeping = false; + } + } + if ( !islandSleeping ) + { + // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures + int numBodies = endIslandIndex - startIslandIndex; + Island* island = allocateIsland( islandId, numBodies ); + island->isSleeping = false; + + // add bodies to island + for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ ) + { + int i = getUnionFind().getElement( iElem ).m_sz; + btCollisionObject* colObj = collisionObjects[ i ]; + island->bodyArray.push_back( colObj ); + } + } + } + +} + + +void btSimulationIslandManagerMt::addManifoldsToIslands( btDispatcher* dispatcher ) +{ + // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island + int maxNumManifolds = dispatcher->getNumManifolds(); + for ( int i = 0; i < maxNumManifolds; i++ ) + { + btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal( i ); + + const btCollisionObject* colObj0 = static_cast( manifold->getBody0() ); + const btCollisionObject* colObj1 = static_cast( manifold->getBody1() ); + + ///@todo: check sleeping conditions! + if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) || + ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) ) + { + + //kinematic objects don't merge islands, but wake up all connected objects + if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING ) + { + if ( colObj0->hasContactResponse() ) + colObj1->activate(); + } + if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING ) + { + if ( colObj1->hasContactResponse() ) + colObj0->activate(); + } + //filtering for response + if ( dispatcher->needsResponse( colObj0, colObj1 ) ) + { + // scatter manifolds into various islands + int islandId = getIslandId( manifold ); + // if island not sleeping, + if ( Island* island = getIsland( islandId ) ) + { + island->manifoldArray.push_back( manifold ); + } + } + } + } +} + + +void btSimulationIslandManagerMt::addConstraintsToIslands( btAlignedObjectArray& constraints ) +{ + // walk constraints + for ( int i = 0; i < constraints.size(); i++ ) + { + // scatter constraints into various islands + btTypedConstraint* constraint = constraints[ i ]; + if ( constraint->isEnabled() ) + { + int islandId = btGetConstraintIslandId( constraint ); + // if island is not sleeping, + if ( Island* island = getIsland( islandId ) ) + { + island->constraintArray.push_back( constraint ); + } + } + } +} + + +void btSimulationIslandManagerMt::mergeIslands() +{ + // sort islands in order of decreasing batch size + m_activeIslands.quickSort( IslandBatchSizeSortPredicate() ); + + // merge small islands to satisfy minimum batch size + // find first small batch island + int destIslandIndex = m_activeIslands.size(); + for ( int i = 0; i < m_activeIslands.size(); ++i ) + { + Island* island = m_activeIslands[ i ]; + int batchSize = calcBatchCost( island ); + if ( batchSize < m_minimumSolverBatchSize ) + { + destIslandIndex = i; + break; + } + } + int lastIndex = m_activeIslands.size() - 1; + while ( destIslandIndex < lastIndex ) + { + // merge islands from the back of the list + Island* island = m_activeIslands[ destIslandIndex ]; + int numBodies = island->bodyArray.size(); + int numManifolds = island->manifoldArray.size(); + int numConstraints = island->constraintArray.size(); + int firstIndex = lastIndex; + // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have + while ( true ) + { + Island* src = m_activeIslands[ firstIndex ]; + numBodies += src->bodyArray.size(); + numManifolds += src->manifoldArray.size(); + numConstraints += src->constraintArray.size(); + int batchCost = calcBatchCost( numBodies, numManifolds, numConstraints ); + if ( batchCost >= m_minimumSolverBatchSize ) + { + break; + } + if ( firstIndex - 1 == destIslandIndex ) + { + break; + } + firstIndex--; + } + // reserve space for these pointers to minimize reallocation + island->bodyArray.reserve( numBodies ); + island->manifoldArray.reserve( numManifolds ); + island->constraintArray.reserve( numConstraints ); + // merge islands + for ( int i = firstIndex; i <= lastIndex; ++i ) + { + island->append( *m_activeIslands[ i ] ); + } + // shrink array to exclude the islands that were merged from + m_activeIslands.resize( firstIndex ); + lastIndex = firstIndex - 1; + destIslandIndex++; + } +} + + +void btSimulationIslandManagerMt::defaultIslandDispatch( btAlignedObjectArray* islandsPtr, IslandCallback* callback ) +{ + // serial dispatch + btAlignedObjectArray& islands = *islandsPtr; + for ( int i = 0; i < islands.size(); ++i ) + { + Island* island = islands[ i ]; + btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL; + btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL; + callback->processIsland( &island->bodyArray[ 0 ], + island->bodyArray.size(), + manifolds, + island->manifoldArray.size(), + constraintsPtr, + island->constraintArray.size(), + island->id + ); + } +} + +///@todo: this is random access, it can be walked 'cache friendly'! +void btSimulationIslandManagerMt::buildAndProcessIslands( btDispatcher* dispatcher, + btCollisionWorld* collisionWorld, + btAlignedObjectArray& constraints, + IslandCallback* callback + ) +{ + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + + buildIslands(dispatcher,collisionWorld); + + BT_PROFILE("processIslands"); + + if(!getSplitIslands()) + { + btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer(); + int maxNumManifolds = dispatcher->getNumManifolds(); + + for ( int i = 0; i < maxNumManifolds; i++ ) + { + btPersistentManifold* manifold = manifolds[ i ]; + + const btCollisionObject* colObj0 = static_cast( manifold->getBody0() ); + const btCollisionObject* colObj1 = static_cast( manifold->getBody1() ); + + ///@todo: check sleeping conditions! + if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) || + ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) ) + { + + //kinematic objects don't merge islands, but wake up all connected objects + if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING ) + { + if ( colObj0->hasContactResponse() ) + colObj1->activate(); + } + if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING ) + { + if ( colObj1->hasContactResponse() ) + colObj0->activate(); + } + } + } + btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[ 0 ] : NULL; + callback->processIsland(&collisionObjects[0], + collisionObjects.size(), + manifolds, + maxNumManifolds, + constraintsPtr, + constraints.size(), + -1 + ); + } + else + { + initIslandPools(); + + //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated + addBodiesToIslands( collisionWorld ); + addManifoldsToIslands( dispatcher ); + addConstraintsToIslands( constraints ); + + // m_activeIslands array should now contain all non-sleeping Islands, and each Island should + // have all the necessary bodies, manifolds and constraints. + + // if we want to merge islands with small batch counts, + if ( m_minimumSolverBatchSize > 1 ) + { + mergeIslands(); + } + // dispatch islands to solver + m_islandDispatch( &m_activeIslands, callback ); + } +} diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h new file mode 100644 index 0000000000..117061623b --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h @@ -0,0 +1,109 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without 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 BT_SIMULATION_ISLAND_MANAGER_MT_H +#define BT_SIMULATION_ISLAND_MANAGER_MT_H + +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +class btTypedConstraint; + + +/// +/// SimulationIslandManagerMt -- Multithread capable version of SimulationIslandManager +/// Splits the world up into islands which can be solved in parallel. +/// In order to solve islands in parallel, an IslandDispatch function +/// must be provided which will dispatch calls to multiple threads. +/// The amount of parallelism that can be achieved depends on the number +/// of islands. If only a single island exists, then no parallelism is +/// possible. +/// +class btSimulationIslandManagerMt : public btSimulationIslandManager +{ +public: + struct Island + { + // a simulation island consisting of bodies, manifolds and constraints, + // to be passed into a constraint solver. + btAlignedObjectArray bodyArray; + btAlignedObjectArray manifoldArray; + btAlignedObjectArray constraintArray; + int id; // island id + bool isSleeping; + + void append( const Island& other ); // add bodies, manifolds, constraints to my own + }; + struct IslandCallback + { + virtual ~IslandCallback() {}; + + virtual void processIsland( btCollisionObject** bodies, + int numBodies, + btPersistentManifold** manifolds, + int numManifolds, + btTypedConstraint** constraints, + int numConstraints, + int islandId + ) = 0; + }; + typedef void( *IslandDispatchFunc ) ( btAlignedObjectArray* islands, IslandCallback* callback ); + static void defaultIslandDispatch( btAlignedObjectArray* islands, IslandCallback* callback ); +protected: + btAlignedObjectArray m_allocatedIslands; // owner of all Islands + btAlignedObjectArray m_activeIslands; // islands actively in use + btAlignedObjectArray m_freeIslands; // islands ready to be reused + btAlignedObjectArray m_lookupIslandFromId; // big lookup table to map islandId to Island pointer + Island* m_batchIsland; + int m_minimumSolverBatchSize; + int m_batchIslandMinBodyCount; + IslandDispatchFunc m_islandDispatch; + + Island* getIsland( int id ); + virtual Island* allocateIsland( int id, int numBodies ); + virtual void initIslandPools(); + virtual void addBodiesToIslands( btCollisionWorld* collisionWorld ); + virtual void addManifoldsToIslands( btDispatcher* dispatcher ); + virtual void addConstraintsToIslands( btAlignedObjectArray& constraints ); + virtual void mergeIslands(); + +public: + btSimulationIslandManagerMt(); + virtual ~btSimulationIslandManagerMt(); + + virtual void buildAndProcessIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld, btAlignedObjectArray& constraints, IslandCallback* callback ); + + virtual void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); + + int getMinimumSolverBatchSize() const + { + return m_minimumSolverBatchSize; + } + void setMinimumSolverBatchSize( int sz ) + { + m_minimumSolverBatchSize = sz; + } + IslandDispatchFunc getIslandDispatchFunction() const + { + return m_islandDispatch; + } + // allow users to set their own dispatch function for multithreaded dispatch + void setIslandDispatchFunction( IslandDispatchFunc func ) + { + m_islandDispatch = func; + } +}; + +#endif //BT_SIMULATION_ISLAND_MANAGER_H + diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp index 51223794a0..ac5c31caf9 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp @@ -6,7 +6,8 @@ * * COPYRIGHT: * Copyright (C) Stephen Thompson, , 2011-2013 - * Portions written By Erwin Coumans: replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix) + * Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix) + * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -20,7 +21,6 @@ */ -// Modified by Lasse Oorni for Urho3D #include "btMultiBody.h" #include "btMultiBodyLink.h" @@ -28,7 +28,6 @@ #include "btMultiBodyJointFeedback.h" #include "LinearMath/btTransformUtil.h" #include "LinearMath/btSerializer.h" -// Urho3D: disable include //#include "Bullet3Common/b3Logging.h" // #define INCLUDE_GYRO_TERM @@ -53,6 +52,7 @@ namespace { bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in; } +#if 0 void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix, const btVector3 &displacement, const btVector3 &top_in, @@ -82,6 +82,8 @@ namespace { top_out = a_top.cross(b_top); bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom); } +#endif + } @@ -94,7 +96,7 @@ btMultiBody::btMultiBody(int n_links, const btVector3 &inertia, bool fixedBase, bool canSleep, - bool multiDof) + bool /*deprecatedUseMultiDof*/) : m_baseCollider(0), m_baseName(0), @@ -107,14 +109,15 @@ btMultiBody::btMultiBody(int n_links, m_awake(true), m_canSleep(canSleep), m_sleepTimer(0), - + m_userObjectPointer(0), + m_userIndex2(-1), + m_userIndex(-1), m_linearDamping(0.04f), m_angularDamping(0.04f), m_useGyroTerm(true), m_maxAppliedImpulse(1000.f), m_maxCoordinateVelocity(100.f), m_hasSelfCollision(true), - m_isMultiDof(multiDof), __posUpdated(false), m_dofCount(0), m_posVarCnt(0), @@ -122,18 +125,15 @@ btMultiBody::btMultiBody(int n_links, m_useGlobalVelocities(false), m_internalNeedsJointFeedback(false) { - - if(!m_isMultiDof) - { - m_vectorBuf.resize(2*n_links); - m_realBuf.resize(6 + 2*n_links); - m_posVarCnt = n_links; - } - + m_cachedInertiaTopLeft.setValue(0,0,0,0,0,0,0,0,0); + m_cachedInertiaTopRight.setValue(0,0,0,0,0,0,0,0,0); + m_cachedInertiaLowerLeft.setValue(0,0,0,0,0,0,0,0,0); + m_cachedInertiaLowerRight.setValue(0,0,0,0,0,0,0,0,0); + m_cachedInertiaValid=false; + m_links.resize(n_links); m_matrixBuf.resize(n_links + 1); - m_baseForce.setValue(0, 0, 0); m_baseTorque.setValue(0, 0, 0); } @@ -148,11 +148,9 @@ void btMultiBody::setupFixed(int i, int parent, const btQuaternion &rotParentToThis, const btVector3 &parentComToThisPivotOffset, - const btVector3 &thisPivotToThisComOffset, - bool disableParentCollision) + const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/) { - btAssert(m_isMultiDof); - + m_links[i].m_mass = mass; m_links[i].m_inertiaLocal = inertia; m_links[i].m_parent = parent; @@ -164,15 +162,10 @@ void btMultiBody::setupFixed(int i, m_links[i].m_dofCount = 0; m_links[i].m_posVarCount = 0; - if (disableParentCollision) - m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; - // + m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; + m_links[i].updateCacheMultiDof(); - // - //if(m_isMultiDof) - // resizeInternalMultiDofBuffers(); - // updateLinksDofOffsets(); } @@ -188,12 +181,9 @@ void btMultiBody::setupPrismatic(int i, const btVector3 &thisPivotToThisComOffset, bool disableParentCollision) { - if(m_isMultiDof) - { - m_dofCount += 1; - m_posVarCnt += 1; - } - + m_dofCount += 1; + m_posVarCnt += 1; + m_links[i].m_mass = mass; m_links[i].m_inertiaLocal = inertia; m_links[i].m_parent = parent; @@ -213,13 +203,10 @@ void btMultiBody::setupPrismatic(int i, if (disableParentCollision) m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; // - if(m_isMultiDof) - m_links[i].updateCacheMultiDof(); - else - m_links[i].updateCache(); - // - if(m_isMultiDof) - updateLinksDofOffsets(); + + m_links[i].updateCacheMultiDof(); + + updateLinksDofOffsets(); } void btMultiBody::setupRevolute(int i, @@ -232,12 +219,9 @@ void btMultiBody::setupRevolute(int i, const btVector3 &thisPivotToThisComOffset, bool disableParentCollision) { - if(m_isMultiDof) - { - m_dofCount += 1; - m_posVarCnt += 1; - } - + m_dofCount += 1; + m_posVarCnt += 1; + m_links[i].m_mass = mass; m_links[i].m_inertiaLocal = inertia; m_links[i].m_parent = parent; @@ -256,13 +240,9 @@ void btMultiBody::setupRevolute(int i, if (disableParentCollision) m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; // - if(m_isMultiDof) - m_links[i].updateCacheMultiDof(); - else - m_links[i].updateCache(); + m_links[i].updateCacheMultiDof(); // - if(m_isMultiDof) - updateLinksDofOffsets(); + updateLinksDofOffsets(); } @@ -276,7 +256,7 @@ void btMultiBody::setupSpherical(int i, const btVector3 &thisPivotToThisComOffset, bool disableParentCollision) { - btAssert(m_isMultiDof); + m_dofCount += 3; m_posVarCnt += 4; @@ -317,7 +297,7 @@ void btMultiBody::setupPlanar(int i, const btVector3 &parentComToThisComOffset, bool disableParentCollision) { - btAssert(m_isMultiDof); + m_dofCount += 3; m_posVarCnt += 3; @@ -329,7 +309,7 @@ void btMultiBody::setupPlanar(int i, m_links[i].m_eVector = parentComToThisComOffset; // - static btVector3 vecNonParallelToRotAxis(1, 0, 0); + btVector3 vecNonParallelToRotAxis(1, 0, 0); if(rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999) vecNonParallelToRotAxis.setValue(0, 1, 0); // @@ -359,7 +339,6 @@ void btMultiBody::setupPlanar(int i, void btMultiBody::finalizeMultiDof() { - btAssert(m_isMultiDof); m_deltaV.resize(0); m_deltaV.resize(6 + m_dofCount); m_realBuf.resize(6 + m_dofCount + m_dofCount*m_dofCount + 6 + m_dofCount); //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels") @@ -390,7 +369,7 @@ btScalar btMultiBody::getJointPos(int i) const btScalar btMultiBody::getJointVel(int i) const { - return m_realBuf[6 + i]; + return m_realBuf[6 + m_links[i].m_dofOffset]; } btScalar * btMultiBody::getJointPosMultiDof(int i) @@ -417,7 +396,7 @@ const btScalar * btMultiBody::getJointVelMultiDof(int i) const void btMultiBody::setJointPos(int i, btScalar q) { m_links[i].m_jointPos[0] = q; - m_links[i].updateCache(); + m_links[i].updateCacheMultiDof(); } void btMultiBody::setJointPosMultiDof(int i, btScalar *q) @@ -430,7 +409,7 @@ void btMultiBody::setJointPosMultiDof(int i, btScalar *q) void btMultiBody::setJointVel(int i, btScalar qdot) { - m_realBuf[6 + i] = qdot; + m_realBuf[6 + m_links[i].m_dofOffset] = qdot; } void btMultiBody::setJointVelMultiDof(int i, btScalar *qdot) @@ -451,6 +430,13 @@ const btQuaternion & btMultiBody::getParentToLocalRot(int i) const btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const { + btAssert(i>=-1); + btAssert(i=m_links.size())) + { + return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); + } + btVector3 result = local_pos; while (i != -1) { // 'result' is in frame i. transform it to frame parent(i) @@ -468,6 +454,13 @@ btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const { + btAssert(i>=-1); + btAssert(i=m_links.size())) + { + return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); + } + if (i == -1) { // world to base return quatRotate(getWorldToBaseRot(),(world_pos - getBasePos())); @@ -479,6 +472,14 @@ btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const { + btAssert(i>=-1); + btAssert(i=m_links.size())) + { + return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); + } + + btVector3 result = local_dir; while (i != -1) { result = quatRotate(getParentToLocalRot(i).inverse() , result); @@ -490,6 +491,13 @@ btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const { + btAssert(i>=-1); + btAssert(i=m_links.size())) + { + return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); + } + if (i == -1) { return quatRotate(getWorldToBaseRot(), world_dir); } else { @@ -497,6 +505,16 @@ btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const } } +btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const +{ + btMatrix3x3 result = local_frame; + btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0)); + btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1)); + btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2)); + result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]); + return result; +} + void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const { int num_links = getNumLinks(); @@ -584,7 +602,7 @@ void btMultiBody::clearForcesAndTorques() void btMultiBody::clearVelocities() { - for (int i = 0; i < 6 + getNumLinks(); ++i) + for (int i = 0; i < 6 + getNumDofs(); ++i) { m_realBuf[i] = 0.f; } @@ -671,7 +689,7 @@ inline btMatrix3x3 outerProduct(const btVector3& v0, const btVector3& v1) //r #define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed) // -void btMultiBody::stepVelocitiesMultiDof(btScalar dt, +void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt, btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v, btAlignedObjectArray &scratch_m, @@ -687,6 +705,10 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame), // num_links joint acceleration values. + // We added support for multi degree of freedom (multi dof) joints. + // In addition we also can compute the joint reaction forces. This is performed in a second pass, + // so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver) + m_internalNeedsJointFeedback = false; int num_links = getNumLinks(); @@ -741,15 +763,15 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, btScalar * Y = &scratch_r[0]; // //aux variables - static btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence) - static btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do - static btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies - static btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel) - static btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough - static btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors - static btSpatialTransformationMatrix fromParent; //spatial transform from parent to child - static btSymmetricSpatialDyad dyadTemp; //inertia matrix temp - static btSpatialTransformationMatrix fromWorld; + btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence) + btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do + btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies + btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel) + btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough + btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors + btSpatialTransformationMatrix fromParent; //spatial transform from parent to child + btSymmetricSpatialDyad dyadTemp; //inertia matrix temp + btSpatialTransformationMatrix fromWorld; fromWorld.m_trnVec.setZero(); ///////////////// @@ -779,8 +801,8 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, //adding damping terms (only) btScalar linDampMult = 1., angDampMult = 1.; - zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().norm()), - linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().norm())); + zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()), + linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm())); // //p += vhat x Ihat vhat - done in a simpler way @@ -866,8 +888,8 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, // //adding damping terms (only) btScalar linDampMult = 1., angDampMult = 1.; - zeroAccSpatFrc[i+1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i+1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i+1].getAngular().norm()), - linDampMult * m_links[i].m_mass * spatVel[i+1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i+1].getLinear().norm())); + zeroAccSpatFrc[i+1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i+1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i+1].getAngular().safeNorm()), + linDampMult * m_links[i].m_mass * spatVel[i+1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i+1].getLinear().safeNorm())); // calculate Ihat_i^A //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs) @@ -946,8 +968,8 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, case btMultibodyLink::eSpherical: case btMultibodyLink::ePlanar: { - static btMatrix3x3 D3x3; D3x3.setValue(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]); - static btMatrix3x3 invD3x3; invD3x3 = D3x3.inverse(); + btMatrix3x3 D3x3; D3x3.setValue(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]); + btMatrix3x3 invD3x3; invD3x3 = D3x3.inverse(); //unroll the loop? for(int row = 0; row < 3; ++row) @@ -1027,6 +1049,7 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, { if (num_links > 0) { + m_cachedInertiaValid = true; m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat; m_cachedInertiaTopRight = spatInertia[0].m_topRightMat; m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat; @@ -1214,320 +1237,6 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, } -void btMultiBody::stepVelocities(btScalar dt, - btAlignedObjectArray &scratch_r, - btAlignedObjectArray &scratch_v, - btAlignedObjectArray &scratch_m) -{ - // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot) - // and the base linear & angular accelerations. - - // We apply damping forces in this routine as well as any external forces specified by the - // caller (via addBaseForce etc). - - // output should point to an array of 6 + num_links reals. - // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame), - // num_links joint acceleration values. - - int num_links = getNumLinks(); - - const btScalar DAMPING_K1_LINEAR = m_linearDamping; - const btScalar DAMPING_K2_LINEAR = m_linearDamping; - - const btScalar DAMPING_K1_ANGULAR = m_angularDamping; - const btScalar DAMPING_K2_ANGULAR= m_angularDamping; - - btVector3 base_vel = getBaseVel(); - btVector3 base_omega = getBaseOmega(); - - // Temporary matrices/vectors -- use scratch space from caller - // so that we don't have to keep reallocating every frame - - scratch_r.resize(2*num_links + 6); - scratch_v.resize(8*num_links + 6); - scratch_m.resize(4*num_links + 4); - - btScalar * r_ptr = &scratch_r[0]; - btScalar * output = &scratch_r[num_links]; // "output" holds the q_double_dot results - btVector3 * v_ptr = &scratch_v[0]; - - // vhat_i (top = angular, bottom = linear part) - btVector3 * vel_top_angular = v_ptr; v_ptr += num_links + 1; - btVector3 * vel_bottom_linear = v_ptr; v_ptr += num_links + 1; - - // zhat_i^A - btVector3 * f_zero_acc_top_angular = v_ptr; v_ptr += num_links + 1; - btVector3 * f_zero_acc_bottom_linear = v_ptr; v_ptr += num_links + 1; - - // chat_i (note NOT defined for the base) - btVector3 * coriolis_top_angular = v_ptr; v_ptr += num_links; - btVector3 * coriolis_bottom_linear = v_ptr; v_ptr += num_links; - - // top left, top right and bottom left blocks of Ihat_i^A. - // bottom right block = transpose of top left block and is not stored. - // Note: the top right and bottom left blocks are always symmetric matrices, but we don't make use of this fact currently. - btMatrix3x3 * inertia_top_left = &scratch_m[num_links + 1]; - btMatrix3x3 * inertia_top_right = &scratch_m[2*num_links + 2]; - btMatrix3x3 * inertia_bottom_left = &scratch_m[3*num_links + 3]; - - // Cached 3x3 rotation matrices from parent frame to this frame. - btMatrix3x3 * rot_from_parent = &m_matrixBuf[0]; - btMatrix3x3 * rot_from_world = &scratch_m[0]; - - // hhat_i, ahat_i - // hhat is NOT stored for the base (but ahat is) - btVector3 * h_top = num_links > 0 ? &m_vectorBuf[0] : 0; - btVector3 * h_bottom = num_links > 0 ? &m_vectorBuf[num_links] : 0; - btVector3 * accel_top = v_ptr; v_ptr += num_links + 1; - btVector3 * accel_bottom = v_ptr; v_ptr += num_links + 1; - - // Y_i, D_i - btScalar * Y1 = r_ptr; r_ptr += num_links; - btScalar * D = num_links > 0 ? &m_realBuf[6 + num_links] : 0; - - // ptr to the joint accel part of the output - btScalar * joint_accel = output + 6; - - - // Start of the algorithm proper. - - // First 'upward' loop. - // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich. - - rot_from_parent[0] = btMatrix3x3(m_baseQuat); - - vel_top_angular[0] = rot_from_parent[0] * base_omega; - vel_bottom_linear[0] = rot_from_parent[0] * base_vel; - - if (m_fixedBase) { - f_zero_acc_top_angular[0] = f_zero_acc_bottom_linear[0] = btVector3(0,0,0); - } else { - f_zero_acc_top_angular[0] = - (rot_from_parent[0] * (m_baseForce - - m_baseMass*(DAMPING_K1_LINEAR+DAMPING_K2_LINEAR*base_vel.norm())*base_vel)); - - f_zero_acc_bottom_linear[0] = - - (rot_from_parent[0] * m_baseTorque); - - if (m_useGyroTerm) - f_zero_acc_bottom_linear[0]+=vel_top_angular[0].cross( m_baseInertia * vel_top_angular[0] ); - - f_zero_acc_bottom_linear[0] += m_baseInertia * vel_top_angular[0] * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR*vel_top_angular[0].norm()); - - } - - - - inertia_top_left[0] = btMatrix3x3(0,0,0,0,0,0,0,0,0);//::Zero(); - - - inertia_top_right[0].setValue(m_baseMass, 0, 0, - 0, m_baseMass, 0, - 0, 0, m_baseMass); - inertia_bottom_left[0].setValue(m_baseInertia[0], 0, 0, - 0, m_baseInertia[1], 0, - 0, 0, m_baseInertia[2]); - - rot_from_world[0] = rot_from_parent[0]; - - for (int i = 0; i < num_links; ++i) { - const int parent = m_links[i].m_parent; - rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis); - - - rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1]; - - // vhat_i = i_xhat_p(i) * vhat_p(i) - SpatialTransform(rot_from_parent[i+1], m_links[i].m_cachedRVector, - vel_top_angular[parent+1], vel_bottom_linear[parent+1], - vel_top_angular[i+1], vel_bottom_linear[i+1]); - - // we can now calculate chat_i - // remember vhat_i is really vhat_p(i) (but in current frame) at this point - coriolis_bottom_linear[i] = vel_top_angular[i+1].cross(vel_top_angular[i+1].cross(m_links[i].m_cachedRVector)) - + 2 * vel_top_angular[i+1].cross(m_links[i].getAxisBottom(0)) * getJointVel(i); - if (m_links[i].m_jointType == btMultibodyLink::eRevolute) { - coriolis_top_angular[i] = vel_top_angular[i+1].cross(m_links[i].getAxisTop(0)) * getJointVel(i); - coriolis_bottom_linear[i] += (getJointVel(i) * getJointVel(i)) * m_links[i].getAxisTop(0).cross(m_links[i].getAxisBottom(0)); - } else { - coriolis_top_angular[i] = btVector3(0,0,0); - } - - // now set vhat_i to its true value by doing - // vhat_i += qidot * shat_i - vel_top_angular[i+1] += getJointVel(i) * m_links[i].getAxisTop(0); - vel_bottom_linear[i+1] += getJointVel(i) * m_links[i].getAxisBottom(0); - - // calculate zhat_i^A - f_zero_acc_top_angular[i+1] = - (rot_from_world[i+1] * (m_links[i].m_appliedForce)); - f_zero_acc_top_angular[i+1] += m_links[i].m_mass * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR*vel_bottom_linear[i+1].norm()) * vel_bottom_linear[i+1]; - - f_zero_acc_bottom_linear[i+1] = - - (rot_from_world[i+1] * m_links[i].m_appliedTorque); - if (m_useGyroTerm) - { - f_zero_acc_bottom_linear[i+1] += vel_top_angular[i+1].cross( m_links[i].m_inertiaLocal * vel_top_angular[i+1] ); - } - - f_zero_acc_bottom_linear[i+1] += m_links[i].m_inertiaLocal * vel_top_angular[i+1] * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR*vel_top_angular[i+1].norm()); - - // calculate Ihat_i^A - inertia_top_left[i+1] = btMatrix3x3(0,0,0,0,0,0,0,0,0);//::Zero(); - inertia_top_right[i+1].setValue(m_links[i].m_mass, 0, 0, - 0, m_links[i].m_mass, 0, - 0, 0, m_links[i].m_mass); - inertia_bottom_left[i+1].setValue(m_links[i].m_inertiaLocal[0], 0, 0, - 0, m_links[i].m_inertiaLocal[1], 0, - 0, 0, m_links[i].m_inertiaLocal[2]); - } - - - // 'Downward' loop. - // (part of TreeForwardDynamics in Mirtich.) - for (int i = num_links - 1; i >= 0; --i) { - - h_top[i] = inertia_top_left[i+1] * m_links[i].getAxisTop(0) + inertia_top_right[i+1] * m_links[i].getAxisBottom(0); - h_bottom[i] = inertia_bottom_left[i+1] * m_links[i].getAxisTop(0) + inertia_top_left[i+1].transpose() * m_links[i].getAxisBottom(0); - btScalar val = SpatialDotProduct(m_links[i].getAxisTop(0), m_links[i].getAxisBottom(0), h_top[i], h_bottom[i]); - D[i] = val; - //Y1 = joint torque - zero acceleration force - coriolis force - Y1[i] = m_links[i].m_jointTorque[0] - - SpatialDotProduct(m_links[i].getAxisTop(0), m_links[i].getAxisBottom(0), f_zero_acc_top_angular[i+1], f_zero_acc_bottom_linear[i+1]) - - SpatialDotProduct(h_top[i], h_bottom[i], coriolis_top_angular[i], coriolis_bottom_linear[i]); - - const int parent = m_links[i].m_parent; - - btAssert(D[i]!=0.f); - // Ip += pXi * (Ii - hi hi' / Di) * iXp - const btScalar one_over_di = 1.0f / D[i]; - - - - - const btMatrix3x3 TL = inertia_top_left[i+1] - vecMulVecTranspose(one_over_di * h_top[i] , h_bottom[i]); - const btMatrix3x3 TR = inertia_top_right[i+1] - vecMulVecTranspose(one_over_di * h_top[i] , h_top[i]); - const btMatrix3x3 BL = inertia_bottom_left[i+1]- vecMulVecTranspose(one_over_di * h_bottom[i] , h_bottom[i]); - - - btMatrix3x3 r_cross; - r_cross.setValue( - 0, -m_links[i].m_cachedRVector[2], m_links[i].m_cachedRVector[1], - m_links[i].m_cachedRVector[2], 0, -m_links[i].m_cachedRVector[0], - -m_links[i].m_cachedRVector[1], m_links[i].m_cachedRVector[0], 0); - - inertia_top_left[parent+1] += rot_from_parent[i+1].transpose() * ( TL - TR * r_cross ) * rot_from_parent[i+1]; - inertia_top_right[parent+1] += rot_from_parent[i+1].transpose() * TR * rot_from_parent[i+1]; - inertia_bottom_left[parent+1] += rot_from_parent[i+1].transpose() * - (r_cross * (TL - TR * r_cross) + BL - TL.transpose() * r_cross) * rot_from_parent[i+1]; - - - // Zp += pXi * (Zi + Ii*ci + hi*Yi/Di) - btVector3 in_top, in_bottom, out_top, out_bottom; - const btScalar Y_over_D = Y1[i] * one_over_di; - in_top = f_zero_acc_top_angular[i+1] - + inertia_top_left[i+1] * coriolis_top_angular[i] - + inertia_top_right[i+1] * coriolis_bottom_linear[i] - + Y_over_D * h_top[i]; - in_bottom = f_zero_acc_bottom_linear[i+1] - + inertia_bottom_left[i+1] * coriolis_top_angular[i] - + inertia_top_left[i+1].transpose() * coriolis_bottom_linear[i] - + Y_over_D * h_bottom[i]; - InverseSpatialTransform(rot_from_parent[i+1], m_links[i].m_cachedRVector, - in_top, in_bottom, out_top, out_bottom); - f_zero_acc_top_angular[parent+1] += out_top; - f_zero_acc_bottom_linear[parent+1] += out_bottom; - } - - - // Second 'upward' loop - // (part of TreeForwardDynamics in Mirtich) - - if (m_fixedBase) - { - accel_top[0] = accel_bottom[0] = btVector3(0,0,0); - } - else - { - if (num_links > 0) - { - //Matrix Imatrix; - //Imatrix.block<3,3>(0,0) = inertia_top_left[0]; - //Imatrix.block<3,3>(3,0) = inertia_bottom_left[0]; - //Imatrix.block<3,3>(0,3) = inertia_top_right[0]; - //Imatrix.block<3,3>(3,3) = inertia_top_left[0].transpose(); - //cached_imatrix_lu.reset(new Eigen::LU >(Imatrix)); // TODO: Avoid memory allocation here? - - m_cachedInertiaTopLeft = inertia_top_left[0]; - m_cachedInertiaTopRight = inertia_top_right[0]; - m_cachedInertiaLowerLeft = inertia_bottom_left[0]; - m_cachedInertiaLowerRight= inertia_top_left[0].transpose(); - - } - btVector3 rhs_top (f_zero_acc_top_angular[0][0], f_zero_acc_top_angular[0][1], f_zero_acc_top_angular[0][2]); - btVector3 rhs_bot (f_zero_acc_bottom_linear[0][0], f_zero_acc_bottom_linear[0][1], f_zero_acc_bottom_linear[0][2]); - float result[6]; - - solveImatrix(rhs_top, rhs_bot, result); -// printf("result=%f,%f,%f,%f,%f,%f\n",result[0],result[0],result[0],result[0],result[0],result[0]); - for (int i = 0; i < 3; ++i) { - accel_top[0][i] = -result[i]; - accel_bottom[0][i] = -result[i+3]; - } - - } - - // now do the loop over the m_links - for (int i = 0; i < num_links; ++i) - { - //acceleration of the child link = acceleration of the parent transformed into child frame + - // + coriolis acceleration - // + joint acceleration - const int parent = m_links[i].m_parent; - SpatialTransform(rot_from_parent[i+1], m_links[i].m_cachedRVector, - accel_top[parent+1], accel_bottom[parent+1], - accel_top[i+1], accel_bottom[i+1]); - - - joint_accel[i] = (Y1[i] - SpatialDotProduct(h_top[i], h_bottom[i], accel_top[i+1], accel_bottom[i+1])) / D[i]; - accel_top[i+1] += coriolis_top_angular[i] + joint_accel[i] * m_links[i].getAxisTop(0); - accel_bottom[i+1] += coriolis_bottom_linear[i] + joint_accel[i] * m_links[i].getAxisBottom(0); - } - - // transform base accelerations back to the world frame. - btVector3 omegadot_out = rot_from_parent[0].transpose() * accel_top[0]; - output[0] = omegadot_out[0]; - output[1] = omegadot_out[1]; - output[2] = omegadot_out[2]; - - btVector3 vdot_out = rot_from_parent[0].transpose() * accel_bottom[0]; - output[3] = vdot_out[0]; - output[4] = vdot_out[1]; - output[5] = vdot_out[2]; - - ///////////////// - //printf("q = ["); - //printf("%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f", m_baseQuat.x(), m_baseQuat.y(), m_baseQuat.z(), m_baseQuat.w(), m_basePos.x(), m_basePos.y(), m_basePos.z()); - //for(int link = 0; link < getNumLinks(); ++link) - // printf("%.2f ", m_links[link].m_jointPos[0]); - //printf("]\n"); - //// - //printf("qd = ["); - //for(int dof = 0; dof < getNumLinks() + 6; ++dof) - // printf("%.2f ", m_realBuf[dof]); - //printf("]\n"); - //// - //printf("qdd = ["); - //for(int dof = 0; dof < getNumLinks() + 6; ++dof) - // printf("%.2f ", output[dof]); - //printf("]\n"); - ///////////////// - - // Final step: add the accelerations (times dt) to the velocities. - //todo: do we already need to update the velocities, or can we move this into the constraint solver? - //the gravity (and other forces) will cause an undesired bounce/restitution effect when using this approach - applyDeltaVee(output, dt); - - -} void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const { @@ -1544,6 +1253,14 @@ void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bo result[5] = rhs_top[2] / m_baseMass; } else { + if (!m_cachedInertiaValid) + { + for (int i=0;i<6;i++) + { + result[i] = 0.f; + } + return; + } /// Special routine for calculating the inverse of a spatial inertia matrix ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f; @@ -1590,6 +1307,13 @@ void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionV { /// Special routine for calculating the inverse of a spatial inertia matrix ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices + if (!m_cachedInertiaValid) + { + result.setLinear(btVector3(0,0,0)); + result.setAngular(btVector3(0,0,0)); + result.setVector(btVector3(0,0,0),btVector3(0,0,0)); + return; + } btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f; btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv; btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse(); @@ -1664,11 +1388,11 @@ void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar btScalar * Y = r_ptr; //////////////// //aux variables - static btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies - static btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel) - static btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough - static btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors - static btSpatialTransformationMatrix fromParent; + btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies + btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel) + btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough + btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors + btSpatialTransformationMatrix fromParent; ///////////////// // First 'upward' loop. @@ -1795,187 +1519,7 @@ void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar } -void btMultiBody::calcAccelerationDeltas(const btScalar *force, btScalar *output, - btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v) const -{ - // Temporary matrices/vectors -- use scratch space from caller - // so that we don't have to keep reallocating every frame - int num_links = getNumLinks(); - scratch_r.resize(num_links); - scratch_v.resize(4*num_links + 4); - - btScalar * r_ptr = num_links == 0 ? 0 : &scratch_r[0]; - btVector3 * v_ptr = &scratch_v[0]; - - // zhat_i^A (scratch space) - btVector3 * zero_acc_top_angular = v_ptr; v_ptr += num_links + 1; - btVector3 * zero_acc_bottom_linear = v_ptr; v_ptr += num_links + 1; - - // rot_from_parent (cached from calcAccelerations) - const btMatrix3x3 * rot_from_parent = &m_matrixBuf[0]; - - // hhat (cached), accel (scratch) - const btVector3 * h_top = num_links > 0 ? &m_vectorBuf[0] : 0; - const btVector3 * h_bottom = num_links > 0 ? &m_vectorBuf[num_links] : 0; - btVector3 * accel_top = v_ptr; v_ptr += num_links + 1; - btVector3 * accel_bottom = v_ptr; v_ptr += num_links + 1; - - // Y_i (scratch), D_i (cached) - btScalar * Y = r_ptr; r_ptr += num_links; - const btScalar * D = num_links > 0 ? &m_realBuf[6 + num_links] : 0; - - btAssert(num_links == 0 || r_ptr - &scratch_r[0] == scratch_r.size()); - btAssert(v_ptr - &scratch_v[0] == scratch_v.size()); - - - - // First 'upward' loop. - // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich. - - btVector3 input_force(force[3],force[4],force[5]); - btVector3 input_torque(force[0],force[1],force[2]); - - // Fill in zero_acc - // -- set to force/torque on the base, zero otherwise - if (m_fixedBase) - { - zero_acc_top_angular[0] = zero_acc_bottom_linear[0] = btVector3(0,0,0); - } else - { - zero_acc_top_angular[0] = - (rot_from_parent[0] * input_force); - zero_acc_bottom_linear[0] = - (rot_from_parent[0] * input_torque); - } - for (int i = 0; i < num_links; ++i) - { - zero_acc_top_angular[i+1] = zero_acc_bottom_linear[i+1] = btVector3(0,0,0); - } - - // 'Downward' loop. - for (int i = num_links - 1; i >= 0; --i) - { -// btScalar sdp = -SpatialDotProduct(m_links[i].getAxisTop(0), m_links[i].getAxisBottom(0), zero_acc_top_angular[i+1], zero_acc_bottom_linear[i+1]); - Y[i] = - SpatialDotProduct(m_links[i].getAxisTop(0), m_links[i].getAxisBottom(0), zero_acc_top_angular[i+1], zero_acc_bottom_linear[i+1]); - Y[i] += force[6 + i]; // add joint torque - - const int parent = m_links[i].m_parent; - - // Zp += pXi * (Zi + hi*Yi/Di) - btVector3 in_top, in_bottom, out_top, out_bottom; - const btScalar Y_over_D = Y[i] / D[i]; - in_top = zero_acc_top_angular[i+1] + Y_over_D * h_top[i]; - in_bottom = zero_acc_bottom_linear[i+1] + Y_over_D * h_bottom[i]; - InverseSpatialTransform(rot_from_parent[i+1], m_links[i].m_cachedRVector, - in_top, in_bottom, out_top, out_bottom); - zero_acc_top_angular[parent+1] += out_top; - zero_acc_bottom_linear[parent+1] += out_bottom; - } - // ptr to the joint accel part of the output - btScalar * joint_accel = output + 6; - - // Second 'upward' loop - if (m_fixedBase) - { - accel_top[0] = accel_bottom[0] = btVector3(0,0,0); - } else - { - btVector3 rhs_top (zero_acc_top_angular[0][0], zero_acc_top_angular[0][1], zero_acc_top_angular[0][2]); - btVector3 rhs_bot (zero_acc_bottom_linear[0][0], zero_acc_bottom_linear[0][1], zero_acc_bottom_linear[0][2]); - - float result[6]; - solveImatrix(rhs_top,rhs_bot, result); - // printf("result=%f,%f,%f,%f,%f,%f\n",result[0],result[0],result[0],result[0],result[0],result[0]); - - for (int i = 0; i < 3; ++i) { - accel_top[0][i] = -result[i]; - accel_bottom[0][i] = -result[i+3]; - } - - } - - // now do the loop over the m_links - for (int i = 0; i < num_links; ++i) { - const int parent = m_links[i].m_parent; - SpatialTransform(rot_from_parent[i+1], m_links[i].m_cachedRVector, - accel_top[parent+1], accel_bottom[parent+1], - accel_top[i+1], accel_bottom[i+1]); - btScalar Y_minus_hT_a = (Y[i] - SpatialDotProduct(h_top[i], h_bottom[i], accel_top[i+1], accel_bottom[i+1])); - joint_accel[i] = Y_minus_hT_a / D[i]; - accel_top[i+1] += joint_accel[i] * m_links[i].getAxisTop(0); - accel_bottom[i+1] += joint_accel[i] * m_links[i].getAxisBottom(0); - } - - // transform base accelerations back to the world frame. - btVector3 omegadot_out; - omegadot_out = rot_from_parent[0].transpose() * accel_top[0]; - output[0] = omegadot_out[0]; - output[1] = omegadot_out[1]; - output[2] = omegadot_out[2]; - - btVector3 vdot_out; - vdot_out = rot_from_parent[0].transpose() * accel_bottom[0]; - - output[3] = vdot_out[0]; - output[4] = vdot_out[1]; - output[5] = vdot_out[2]; - - - ///////////////// - /* - int ndof = getNumLinks() + 6; - printf("test force(impulse) (%d) = [\n",ndof); - - for (int i=0;i &scratch_r, - btAlignedObjectArray &scratch_v, - btAlignedObjectArray &scratch_m) const -{ - // temporary space - int num_links = getNumLinks(); - scratch_v.resize(2*num_links + 2); - scratch_m.resize(num_links + 1); - - btVector3 * v_ptr = &scratch_v[0]; - btVector3 * p_minus_com = v_ptr; v_ptr += num_links + 1; - btVector3 * n_local = v_ptr; v_ptr += num_links + 1; - btAssert(v_ptr - &scratch_v[0] == scratch_v.size()); - - scratch_r.resize(num_links); - btScalar * results = num_links > 0 ? &scratch_r[0] : 0; - - btMatrix3x3 * rot_from_world = &scratch_m[0]; - - const btVector3 p_minus_com_world = contact_point - m_basePos; - - rot_from_world[0] = btMatrix3x3(m_baseQuat); - - p_minus_com[0] = rot_from_world[0] * p_minus_com_world; - n_local[0] = rot_from_world[0] * normal; - - // omega coeffients first. - if (this->m_fixedBase) - { - for (int i=0;i<6;i++) - { - jac[i]=0; - } - } else - { - btVector3 omega_coeffs; - - omega_coeffs = p_minus_com_world.cross(normal); - jac[0] = omega_coeffs[0]; - jac[1] = omega_coeffs[1]; - jac[2] = omega_coeffs[2]; - // then v coefficients - jac[3] = normal[0]; - jac[4] = normal[1]; - jac[5] = normal[2]; - } - // Set remaining jac values to zero for now. - for (int i = 6; i < 6 + num_links; ++i) { - jac[i] = 0; - } - - // Qdot coefficients, if necessary. - if (num_links > 0 && link > -1) { - - // TODO: speed this up -- don't calculate for m_links we don't need. - // (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions, - // which is resulting in repeated work being done...) - - // calculate required normals & positions in the local frames. - for (int i = 0; i < num_links; ++i) { - - // transform to local frame - const int parent = m_links[i].m_parent; - const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis); - rot_from_world[i+1] = mtx * rot_from_world[parent+1]; - - n_local[i+1] = mtx * n_local[parent+1]; - p_minus_com[i+1] = mtx * p_minus_com[parent+1] - m_links[i].m_cachedRVector; - - // calculate the jacobian entry - if (m_links[i].m_jointType == btMultibodyLink::eRevolute) { - results[i] = n_local[i+1].dot( m_links[i].getAxisTop(0).cross(p_minus_com[i+1]) + m_links[i].getAxisBottom(0) ); - } else { - results[i] = n_local[i+1].dot( m_links[i].getAxisBottom(0) ); - } - } - - // Now copy through to output. - //printf("jac[%d] = ", link); - while (link != -1) - { - jac[6 + link] = results[link]; - //printf("%.2f\t", jac[6 + link]); - link = m_links[link].m_parent; - } - //printf("]\n"); - } -} void btMultiBody::wakeUp() { @@ -2345,7 +1797,6 @@ void btMultiBody::goToSleep() void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep) { - int num_links = getNumLinks(); extern bool gDisableDeactivation; if (!m_canSleep || gDisableDeactivation) { @@ -2356,17 +1807,11 @@ void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep) // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities) btScalar motion = 0; - if(m_isMultiDof) { for (int i = 0; i < 6 + m_dofCount; ++i) motion += m_realBuf[i] * m_realBuf[i]; } - else - { - for (int i = 0; i < 6 + num_links; ++i) - motion += m_realBuf[i] * m_realBuf[i]; - } - + if (motion < SLEEP_EPSILON) { m_sleepTimer += timestep; @@ -2518,6 +1963,9 @@ const char* btMultiBody::serialize(void* dataBuffer, class btSerializer* seriali getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia); memPtr->m_linkMass = getLink(i).m_mass; memPtr->m_parentIndex = getLink(i).m_parent; + memPtr->m_jointDamping = getLink(i).m_jointDamping; + memPtr->m_jointFriction = getLink(i).m_jointFriction; + getLink(i).m_eVector.serialize(memPtr->m_parentComToThisComOffset); getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset); getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.h index d090d4b179..2d6f7f5f88 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBody.h @@ -6,7 +6,8 @@ * * COPYRIGHT: * Copyright (C) Stephen Thompson, , 2011-2013 - * Portions written By Erwin Coumans: replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix) + * Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix) + * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements This software is provided 'as-is', without 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,6 +31,8 @@ #include "LinearMath/btMatrix3x3.h" #include "LinearMath/btAlignedObjectArray.h" + +///serialization data, don't change them if you are not familiar with the details of the serialization mechanisms #ifdef BT_USE_DOUBLE_PRECISION #define btMultiBodyData btMultiBodyDoubleData #define btMultiBodyDataName "btMultiBodyDoubleData" @@ -45,7 +48,7 @@ #include "btMultiBodyLink.h" class btMultiBodyLinkCollider; -class btMultiBody +ATTRIBUTE_ALIGNED16(class) btMultiBody { public: @@ -60,21 +63,19 @@ class btMultiBody btScalar mass, // mass of base const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal bool fixedBase, // whether the base is fixed (true) or can move (false) - bool canSleep, - bool multiDof = false - ); + bool canSleep, bool deprecatedMultiDof=true); virtual ~btMultiBody(); + //note: fixed link collision with parent is always disabled void setupFixed(int linkIndex, btScalar mass, const btVector3 &inertia, int parent, const btQuaternion &rotParentToThis, const btVector3 &parentComToThisPivotOffset, - const btVector3 &thisPivotToThisComOffset, - bool disableParentCollision); + const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision=true); void setupPrismatic(int i, @@ -271,7 +272,11 @@ class btMultiBody btVector3 localDirToWorld(int i, const btVector3 &vec) const; btVector3 worldPosToLocal(int i, const btVector3 &vec) const; btVector3 worldDirToLocal(int i, const btVector3 &vec) const; - + + // + // transform a frame in local coordinate to a frame in world coordinate + // + btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &mat) const; // // calculate kinetic energy and angular momentum @@ -336,72 +341,36 @@ void addJointTorque(int i, btScalar Q); // improvement, at least on Windows (where dynamic memory // allocation appears to be fairly slow). // - void stepVelocities(btScalar dt, + + + void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt, btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v, - btAlignedObjectArray &scratch_m); + btAlignedObjectArray &scratch_m, + bool isConstraintPass=false + ); - void stepVelocitiesMultiDof(btScalar dt, +///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead + void stepVelocitiesMultiDof(btScalar dt, btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v, btAlignedObjectArray &scratch_m, - bool isConstraintPass=false - ); + bool isConstraintPass=false) + { + computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt,scratch_r,scratch_v,scratch_m,isConstraintPass); + } - // calcAccelerationDeltas + // calcAccelerationDeltasMultiDof // input: force vector (in same format as jacobian, i.e.: // 3 torque values, 3 force values, num_links joint torque values) // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values // (existing contents of output array are replaced) - // stepVelocities must have been called first. - void calcAccelerationDeltas(const btScalar *force, btScalar *output, - btAlignedObjectArray &scratch_r, - btAlignedObjectArray &scratch_v) const; - + // calcAccelerationDeltasMultiDof must have been called first. void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output, btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v) const; - - // apply a delta-vee directly. used in sequential impulses code. - void applyDeltaVee(const btScalar * delta_vee) - { - - for (int i = 0; i < 6 + getNumLinks(); ++i) - { - m_realBuf[i] += delta_vee[i]; - } - - } - void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier) - { - btScalar sum = 0; - for (int i = 0; i < 6 + getNumLinks(); ++i) - { - sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier; - } - btScalar l = btSqrt(sum); - /* - static btScalar maxl = -1e30f; - if (l>maxl) - { - maxl=l; - // printf("maxl=%f\n",maxl); - } - */ - if (l>m_maxAppliedImpulse) - { -// printf("exceeds 100: l=%f\n",maxl); - multiplier *= m_maxAppliedImpulse/l; - } - - for (int i = 0; i < 6 + getNumLinks(); ++i) - { - sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier; - m_realBuf[i] += delta_vee[i] * multiplier; - btClamp(m_realBuf[i],-m_maxCoordinateVelocity,m_maxCoordinateVelocity); - } - } - + + void applyDeltaVeeMultiDof2(const btScalar * delta_vee, btScalar multiplier) { for (int dof = 0; dof < 6 + getNumDofs(); ++dof) @@ -447,7 +416,6 @@ void addJointTorque(int i, btScalar Q); // timestep the positions (given current velocities). - void stepPositions(btScalar dt); void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0); @@ -458,26 +426,18 @@ void addJointTorque(int i, btScalar Q); // This routine fills out a contact constraint jacobian for this body. // the 'normal' supplied must be -n for body1 or +n for body2 of the contact. // 'normal' & 'contact_point' are both given in world coordinates. - void fillContactJacobian(int link, - const btVector3 &contact_point, - const btVector3 &normal, - btScalar *jac, - btAlignedObjectArray &scratch_r, - btAlignedObjectArray &scratch_v, - btAlignedObjectArray &scratch_m) const; - - //multidof version of fillContactJacobian + void fillContactJacobianMultiDof(int link, const btVector3 &contact_point, const btVector3 &normal, btScalar *jac, btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v, - btAlignedObjectArray &scratch_m) const { filConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); } + btAlignedObjectArray &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); } //a more general version of fillContactJacobianMultiDof which does not assume.. //.. that the constraint in question is contact or, to be more precise, constrains linear velocity only - void filConstraintJacobianMultiDof(int link, + void fillConstraintJacobianMultiDof(int link, const btVector3 &contact_point, const btVector3 &normal_ang, const btVector3 &normal_lin, @@ -576,7 +536,7 @@ void addJointTorque(int i, btScalar Q); return m_hasSelfCollision; } - bool isMultiDof() { return m_isMultiDof; } + void finalizeMultiDof(); void useRK4Integration(bool use) { m_useRK4 = use; } @@ -600,6 +560,8 @@ void addJointTorque(int i, btScalar Q); } void forwardKinematics(btAlignedObjectArray& scratch_q,btAlignedObjectArray& scratch_m); + void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const; + void updateCollisionObjectWorldTransforms(btAlignedObjectArray& scratch_q,btAlignedObjectArray& scratch_m); virtual int calculateSerializeBufferSize() const; @@ -617,11 +579,42 @@ void addJointTorque(int i, btScalar Q); m_baseName = name; } + ///users can point to their objects, userPointer is not used by Bullet + void* getUserPointer() const + { + return m_userObjectPointer; + } + + int getUserIndex() const + { + return m_userIndex; + } + + int getUserIndex2() const + { + return m_userIndex2; + } + ///users can point to their objects, userPointer is not used by Bullet + void setUserPointer(void* userPointer) + { + m_userObjectPointer = userPointer; + } + + ///users can point to their objects, userPointer is not used by Bullet + void setUserIndex(int index) + { + m_userIndex = index; + } + + void setUserIndex2(int index) + { + m_userIndex2 = index; + } + private: btMultiBody(const btMultiBody &); // not implemented void operator=(const btMultiBody &); // not implemented - void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const; void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const; void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const; @@ -685,6 +678,7 @@ void addJointTorque(int i, btScalar Q); btMatrix3x3 m_cachedInertiaTopRight; btMatrix3x3 m_cachedInertiaLowerLeft; btMatrix3x3 m_cachedInertiaLowerRight; + bool m_cachedInertiaValid; bool m_fixedBase; @@ -693,6 +687,10 @@ void addJointTorque(int i, btScalar Q); bool m_canSleep; btScalar m_sleepTimer; + void* m_userObjectPointer; + int m_userIndex2; + int m_userIndex; + int m_companionId; btScalar m_linearDamping; btScalar m_angularDamping; @@ -700,7 +698,7 @@ void addJointTorque(int i, btScalar Q); btScalar m_maxAppliedImpulse; btScalar m_maxCoordinateVelocity; bool m_hasSelfCollision; - bool m_isMultiDof; + bool __posUpdated; int m_dofCount, m_posVarCnt; bool m_useRK4, m_useGlobalVelocities; @@ -717,27 +715,25 @@ struct btMultiBodyLinkDoubleData btVector3DoubleData m_jointAxisTop[6]; btVector3DoubleData m_jointAxisBottom[6]; - - char *m_linkName; - char *m_jointName; - btCollisionObjectDoubleData *m_linkCollider; - btVector3DoubleData m_linkInertia; // inertia of the base (in local frame; diagonal) double m_linkMass; int m_parentIndex; int m_jointType; - - - int m_dofCount; int m_posVarCount; double m_jointPos[7]; double m_jointVel[6]; double m_jointTorque[6]; - - - + + double m_jointDamping; + double m_jointFriction; + + char *m_linkName; + char *m_jointName; + btCollisionObjectDoubleData *m_linkCollider; + char *m_paddingPtr; + }; struct btMultiBodyLinkFloatData @@ -747,12 +743,6 @@ struct btMultiBodyLinkFloatData btVector3FloatData m_thisPivotToThisComOffset; btVector3FloatData m_jointAxisTop[6]; btVector3FloatData m_jointAxisBottom[6]; - - - char *m_linkName; - char *m_jointName; - btCollisionObjectFloatData *m_linkCollider; - btVector3FloatData m_linkInertia; // inertia of the base (in local frame; diagonal) int m_dofCount; float m_linkMass; @@ -765,25 +755,29 @@ struct btMultiBodyLinkFloatData float m_jointVel[6]; float m_jointTorque[6]; int m_posVarCount; - + float m_jointDamping; + float m_jointFriction; + + char *m_linkName; + char *m_jointName; + btCollisionObjectFloatData *m_linkCollider; + char *m_paddingPtr; }; ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 struct btMultiBodyDoubleData { - char *m_baseName; - btMultiBodyLinkDoubleData *m_links; - btCollisionObjectDoubleData *m_baseCollider; - btTransformDoubleData m_baseWorldTransform; btVector3DoubleData m_baseInertia; // inertia of the base (in local frame; diagonal) - - int m_numLinks; double m_baseMass; - char m_padding[4]; - + char *m_baseName; + btMultiBodyLinkDoubleData *m_links; + btCollisionObjectDoubleData *m_baseCollider; + char *m_paddingPtr; + int m_numLinks; + char m_padding[4]; }; ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp index e9e285f3fa..d52852dd8e 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp @@ -23,18 +23,12 @@ void btMultiBodyConstraint::updateJacobianSizes() { if(m_bodyA) { - if(m_bodyA->isMultiDof()) - m_jacSizeA = (6 + m_bodyA->getNumDofs()); - else - m_jacSizeA = (6 + m_bodyA->getNumLinks()); + m_jacSizeA = (6 + m_bodyA->getNumDofs()); } if(m_bodyB) { - if(m_bodyB->isMultiDof()) - m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumDofs(); - else - m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumLinks(); + m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumDofs(); } else m_jacSizeBoth = m_jacSizeA; @@ -59,335 +53,365 @@ void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScala } btScalar btMultiBodyConstraint::fillMultiBodyConstraint( btMultiBodySolverConstraint& solverConstraint, - btMultiBodyJacobianData& data, - btScalar* jacOrgA, btScalar* jacOrgB, - const btVector3& contactNormalOnB, - const btVector3& posAworld, const btVector3& posBworld, - btScalar posError, - const btContactSolverInfo& infoGlobal, - btScalar lowerLimit, btScalar upperLimit, - btScalar relaxation, - bool isFriction, btScalar desiredVelocity, btScalar cfmSlip) + btMultiBodyJacobianData& data, + btScalar* jacOrgA, btScalar* jacOrgB, + const btVector3& constraintNormalAng, + const btVector3& constraintNormalLin, + const btVector3& posAworld, const btVector3& posBworld, + btScalar posError, + const btContactSolverInfo& infoGlobal, + btScalar lowerLimit, btScalar upperLimit, + bool angConstraint, + btScalar relaxation, + bool isFriction, btScalar desiredVelocity, btScalar cfmSlip) { - - - solverConstraint.m_multiBodyA = m_bodyA; - solverConstraint.m_multiBodyB = m_bodyB; - solverConstraint.m_linkA = m_linkA; - solverConstraint.m_linkB = m_linkB; - - btMultiBody* multiBodyA = solverConstraint.m_multiBodyA; - btMultiBody* multiBodyB = solverConstraint.m_multiBodyB; - - btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA); - btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB); - - btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody; - btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody; - - btVector3 rel_pos1, rel_pos2; //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary - if (bodyA) - rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin(); - if (bodyB) - rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin(); - - if (multiBodyA) - { - if (solverConstraint.m_linkA<0) - { - rel_pos1 = posAworld - multiBodyA->getBasePos(); - } else - { - rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin(); - } - - const int ndofA = (multiBodyA->isMultiDof() ? multiBodyA->getNumDofs() : multiBodyA->getNumLinks()) + 6; - - solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId(); - - if (solverConstraint.m_deltaVelAindex <0) - { - solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size(); - multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex); - data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofA); - } else - { - btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA); - } - - //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom - //resize.. - solverConstraint.m_jacAindex = data.m_jacobians.size(); - data.m_jacobians.resize(data.m_jacobians.size()+ndofA); - //copy/determine - if(jacOrgA) - { - for (int i=0;iisMultiDof()) - multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, contactNormalOnB, jac1, data.scratch_r, data.scratch_v, data.scratch_m); - else - multiBodyA->fillContactJacobian(solverConstraint.m_linkA, posAworld, contactNormalOnB, jac1, data.scratch_r, data.scratch_v, data.scratch_m); - } - - //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint) - //resize.. - data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofA); //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse - btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); - btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; - //determine.. - if(multiBodyA->isMultiDof()) - multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex],delta,data.scratch_r, data.scratch_v); - else - multiBodyA->calcAccelerationDeltas(&data.m_jacobians[solverConstraint.m_jacAindex],delta,data.scratch_r, data.scratch_v); - - btVector3 torqueAxis0 = rel_pos1.cross(contactNormalOnB); - solverConstraint.m_relpos1CrossNormal = torqueAxis0; - solverConstraint.m_contactNormal1 = contactNormalOnB; - } - else //if(rb0) - { - btVector3 torqueAxis0 = rel_pos1.cross(contactNormalOnB); - solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); - solverConstraint.m_relpos1CrossNormal = torqueAxis0; - solverConstraint.m_contactNormal1 = contactNormalOnB; - } - - if (multiBodyB) - { - if (solverConstraint.m_linkB<0) - { - rel_pos2 = posBworld - multiBodyB->getBasePos(); - } else - { - rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin(); - } - - const int ndofB = (multiBodyB->isMultiDof() ? multiBodyB->getNumDofs() : multiBodyB->getNumLinks()) + 6; - - solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId(); - if (solverConstraint.m_deltaVelBindex <0) - { - solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size(); - multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex); - data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofB); - } - - //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom - //resize.. - solverConstraint.m_jacBindex = data.m_jacobians.size(); - data.m_jacobians.resize(data.m_jacobians.size()+ndofB); - //copy/determine.. - if(jacOrgB) - { - for (int i=0;iisMultiDof()) - multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -contactNormalOnB, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m); - else - multiBodyB->fillContactJacobian(solverConstraint.m_linkB, posBworld, -contactNormalOnB, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m); - } - - //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint) - //resize.. - data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofB); - btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); - btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; - //determine.. - if(multiBodyB->isMultiDof()) - multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex],delta,data.scratch_r, data.scratch_v); - else - multiBodyB->calcAccelerationDeltas(&data.m_jacobians[solverConstraint.m_jacBindex],delta,data.scratch_r, data.scratch_v); - - btVector3 torqueAxis1 = rel_pos2.cross(contactNormalOnB); - solverConstraint.m_relpos2CrossNormal = -torqueAxis1; - solverConstraint.m_contactNormal2 = -contactNormalOnB; - - } - else //if(rb1) - { - btVector3 torqueAxis1 = rel_pos2.cross(contactNormalOnB); - solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); - solverConstraint.m_relpos2CrossNormal = -torqueAxis1; - solverConstraint.m_contactNormal2 = -contactNormalOnB; - } - { - - btVector3 vec; - btScalar denom0 = 0.f; - btScalar denom1 = 0.f; - btScalar* jacB = 0; - btScalar* jacA = 0; - btScalar* deltaVelA = 0; - btScalar* deltaVelB = 0; - int ndofA = 0; - //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i]) - if (multiBodyA) - { - ndofA = (multiBodyA->isMultiDof() ? multiBodyA->getNumDofs() : multiBodyA->getNumLinks()) + 6; - jacA = &data.m_jacobians[solverConstraint.m_jacAindex]; - deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; - for (int i = 0; i < ndofA; ++i) - { - btScalar j = jacA[i] ; - btScalar l = deltaVelA[i]; - denom0 += j*l; - } - } - else if(rb0) - { - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); - denom0 = rb0->getInvMass() + contactNormalOnB.dot(vec); - } - // - if (multiBodyB) - { - const int ndofB = (multiBodyB->isMultiDof() ? multiBodyB->getNumDofs() : multiBodyB->getNumLinks()) + 6; - jacB = &data.m_jacobians[solverConstraint.m_jacBindex]; - deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; - for (int i = 0; i < ndofB; ++i) - { - btScalar j = jacB[i] ; - btScalar l = deltaVelB[i]; - denom1 += j*l; - } - - } - else if(rb1) - { - vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); - denom1 = rb1->getInvMass() + contactNormalOnB.dot(vec); - } - - // - btScalar d = denom0+denom1; - if (d>SIMD_EPSILON) - { - solverConstraint.m_jacDiagABInv = relaxation/(d); - } - else - { - //disable the constraint row to handle singularity/redundant constraint - solverConstraint.m_jacDiagABInv = 0.f; - } - } - - - //compute rhs and remaining solverConstraint fields - btScalar penetration = isFriction? 0 : posError+infoGlobal.m_linearSlop; - - btScalar rel_vel = 0.f; - int ndofA = 0; - int ndofB = 0; - { - btVector3 vel1,vel2; - if (multiBodyA) - { - ndofA = (multiBodyA->isMultiDof() ? multiBodyA->getNumDofs() : multiBodyA->getNumLinks()) + 6; - btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex]; - for (int i = 0; i < ndofA ; ++i) - rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; - } - else if(rb0) - { - rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1); - } - if (multiBodyB) - { - ndofB = (multiBodyB->isMultiDof() ? multiBodyB->getNumDofs() : multiBodyB->getNumLinks()) + 6; - btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex]; - for (int i = 0; i < ndofB ; ++i) - rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; - - } - else if(rb1) - { - rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2); - } - - solverConstraint.m_friction = 0.f;//cp.m_combinedFriction; - } - - - ///warm starting (or zero if disabled) - /* - if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; - - if (solverConstraint.m_appliedImpulse) - { - if (multiBodyA) - { - btScalar impulse = solverConstraint.m_appliedImpulse; - btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; - multiBodyA->applyDeltaVee(deltaV,impulse); - applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA); - } else - { - if (rb0) + solverConstraint.m_multiBodyA = m_bodyA; + solverConstraint.m_multiBodyB = m_bodyB; + solverConstraint.m_linkA = m_linkA; + solverConstraint.m_linkB = m_linkB; + + btMultiBody* multiBodyA = solverConstraint.m_multiBodyA; + btMultiBody* multiBodyB = solverConstraint.m_multiBodyB; + + btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA); + btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB); + + btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody; + btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody; + + btVector3 rel_pos1, rel_pos2; //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary + if (bodyA) + rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin(); + if (bodyB) + rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin(); + + if (multiBodyA) + { + if (solverConstraint.m_linkA<0) + { + rel_pos1 = posAworld - multiBodyA->getBasePos(); + } else + { + rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin(); + } + + const int ndofA = multiBodyA->getNumDofs() + 6; + + solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId(); + + if (solverConstraint.m_deltaVelAindex <0) + { + solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size(); + multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex); + data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofA); + } else + { + btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA); + } + + //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom + //resize.. + solverConstraint.m_jacAindex = data.m_jacobians.size(); + data.m_jacobians.resize(data.m_jacobians.size()+ndofA); + //copy/determine + if(jacOrgA) + { + for (int i=0;ifillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m); + multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalAng, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m); + } + + //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint) + //resize.. + data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofA); //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse + btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); + btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + //determine.. + multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex],delta,data.scratch_r, data.scratch_v); + + btVector3 torqueAxis0; + if (angConstraint) { + torqueAxis0 = constraintNormalAng; + } + else { + torqueAxis0 = rel_pos1.cross(constraintNormalLin); + + } + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + solverConstraint.m_contactNormal1 = constraintNormalLin; + } + else //if(rb0) + { + btVector3 torqueAxis0; + if (angConstraint) { + torqueAxis0 = constraintNormalAng; + } + else { + torqueAxis0 = rel_pos1.cross(constraintNormalLin); + } + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + solverConstraint.m_contactNormal1 = constraintNormalLin; + } + + if (multiBodyB) + { + if (solverConstraint.m_linkB<0) + { + rel_pos2 = posBworld - multiBodyB->getBasePos(); + } else + { + rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin(); + } + + const int ndofB = multiBodyB->getNumDofs() + 6; + + solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId(); + if (solverConstraint.m_deltaVelBindex <0) + { + solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size(); + multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex); + data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofB); + } + + //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom + //resize.. + solverConstraint.m_jacBindex = data.m_jacobians.size(); + data.m_jacobians.resize(data.m_jacobians.size()+ndofB); + //copy/determine.. + if(jacOrgB) + { + for (int i=0;ifillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m); + multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalAng, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m); + } + + //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint) + //resize.. + data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofB); + btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); + btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + //determine.. + multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex],delta,data.scratch_r, data.scratch_v); + + btVector3 torqueAxis1; + if (angConstraint) { + torqueAxis1 = constraintNormalAng; + } + else { + torqueAxis1 = rel_pos2.cross(constraintNormalLin); + } + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + solverConstraint.m_contactNormal2 = -constraintNormalLin; + } + else //if(rb1) + { + btVector3 torqueAxis1; + if (angConstraint) { + torqueAxis1 = constraintNormalAng; + } + else { + torqueAxis1 = rel_pos2.cross(constraintNormalLin); + } + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + solverConstraint.m_contactNormal2 = -constraintNormalLin; + } + { + + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + btScalar* jacB = 0; + btScalar* jacA = 0; + btScalar* deltaVelA = 0; + btScalar* deltaVelB = 0; + int ndofA = 0; + //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i]) + if (multiBodyA) + { + ndofA = multiBodyA->getNumDofs() + 6; + jacA = &data.m_jacobians[solverConstraint.m_jacAindex]; + deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA; ++i) + { + btScalar j = jacA[i] ; + btScalar l = deltaVelA[i]; + denom0 += j*l; + } + } + else if(rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + if (angConstraint) { + denom0 = rb0->getInvMass() + constraintNormalAng.dot(vec); + } + else { + denom0 = rb0->getInvMass() + constraintNormalLin.dot(vec); + } + } + // + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumDofs() + 6; + jacB = &data.m_jacobians[solverConstraint.m_jacBindex]; + deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB; ++i) + { + btScalar j = jacB[i] ; + btScalar l = deltaVelB[i]; + denom1 += j*l; + } + + } + else if(rb1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + if (angConstraint) { + denom1 = rb1->getInvMass() + constraintNormalAng.dot(vec); + } + else { + denom1 = rb1->getInvMass() + constraintNormalLin.dot(vec); + } + } + + // + btScalar d = denom0+denom1; + if (d>SIMD_EPSILON) + { + solverConstraint.m_jacDiagABInv = relaxation/(d); + } + else + { + //disable the constraint row to handle singularity/redundant constraint + solverConstraint.m_jacDiagABInv = 0.f; + } + } + + + //compute rhs and remaining solverConstraint fields + btScalar penetration = isFriction? 0 : posError; + + btScalar rel_vel = 0.f; + int ndofA = 0; + int ndofB = 0; + { + btVector3 vel1,vel2; + if (multiBodyA) + { + ndofA = multiBodyA->getNumDofs() + 6; + btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA ; ++i) + rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; + } + else if(rb0) + { + rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1); + } + if (multiBodyB) + { + ndofB = multiBodyB->getNumDofs() + 6; + btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB ; ++i) + rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; + + } + else if(rb1) + { + rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2); + } + + solverConstraint.m_friction = 0.f;//cp.m_combinedFriction; + } + + + ///warm starting (or zero if disabled) + /* + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + + if (solverConstraint.m_appliedImpulse) + { + if (multiBodyA) + { + btScalar impulse = solverConstraint.m_appliedImpulse; + btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + multiBodyA->applyDeltaVee(deltaV,impulse); + applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA); + } else + { + if (rb0) bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); - } - if (multiBodyB) - { - btScalar impulse = solverConstraint.m_appliedImpulse; - btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; - multiBodyB->applyDeltaVee(deltaV,impulse); - applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB); - } else - { - if (rb1) + } + if (multiBodyB) + { + btScalar impulse = solverConstraint.m_appliedImpulse; + btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + multiBodyB->applyDeltaVee(deltaV,impulse); + applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB); + } else + { + if (rb1) bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse); - } - } - } else - */ - - solverConstraint.m_appliedImpulse = 0.f; - solverConstraint.m_appliedPushImpulse = 0.f; - - { - - btScalar positionalError = 0.f; - btScalar velocityError = desiredVelocity - rel_vel;// * damping; - - - btScalar erp = infoGlobal.m_erp2; - if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) - { - erp = infoGlobal.m_erp; - } - - positionalError = -penetration * erp/infoGlobal.m_timeStep; - - btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; - - if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) - { - //combine position and velocity into rhs - solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; - solverConstraint.m_rhsPenetration = 0.f; - - } else - { - //split position and velocity into rhs and m_rhsPenetration - solverConstraint.m_rhs = velocityImpulse; - solverConstraint.m_rhsPenetration = penetrationImpulse; - } - - solverConstraint.m_cfm = 0.f; - solverConstraint.m_lowerLimit = lowerLimit; - solverConstraint.m_upperLimit = upperLimit; - } - - return rel_vel; - + } + } + } else + */ + + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedPushImpulse = 0.f; + + { + + btScalar positionalError = 0.f; + btScalar velocityError = desiredVelocity - rel_vel;// * damping; + + + btScalar erp = infoGlobal.m_erp2; + + //split impulse is not implemented yet for btMultiBody* + //if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + erp = infoGlobal.m_erp; + } + + positionalError = -penetration * erp/infoGlobal.m_timeStep; + + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + + //split impulse is not implemented yet for btMultiBody* + + // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_rhsPenetration = 0.f; + + } + /*else + { + //split position and velocity into rhs and m_rhsPenetration + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = penetrationImpulse; + } + */ + + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = lowerLimit; + solverConstraint.m_upperLimit = upperLimit; + } + + return rel_vel; + } diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h index 3b32b46e91..7204f27854 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h @@ -39,7 +39,7 @@ struct btMultiBodyJacobianData }; -class btMultiBodyConstraint +ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraint { protected: @@ -66,26 +66,36 @@ class btMultiBodyConstraint btAlignedObjectArray m_data; void applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof); - + btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint& solverConstraint, btMultiBodyJacobianData& data, - btScalar* jacOrgA, btScalar* jacOrgB, - const btVector3& contactNormalOnB, + btScalar* jacOrgA, btScalar* jacOrgB, + const btVector3& constraintNormalAng, + + const btVector3& constraintNormalLin, const btVector3& posAworld, const btVector3& posBworld, btScalar posError, const btContactSolverInfo& infoGlobal, - btScalar lowerLimit, btScalar upperLimit, + btScalar lowerLimit, btScalar upperLimit, + bool angConstraint = false, + btScalar relaxation = 1.f, bool isFriction = false, btScalar desiredVelocity=0, btScalar cfmSlip=0); public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral); virtual ~btMultiBodyConstraint(); void updateJacobianSizes(); void allocateJacobiansMultiDof(); + //many constraints have setFrameInB/setPivotInB. Will use 'getConstraintType' later. + virtual void setFrameInB(const btMatrix3x3& frameInB) {} + virtual void setPivotInB(const btVector3& pivotInB){} + virtual void finalizeMultiDof()=0; virtual int getIslandIdA() const =0; @@ -114,6 +124,7 @@ class btMultiBodyConstraint btAssert(dof>=0); btAssert(dof < getNumRows()); m_data[dof] = appliedImpulse; + } btScalar getAppliedImpulse(int dof) diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp index 2ebd4696ae..903ef8d6da 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp @@ -13,7 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -// Modified by Lasse Oorni for Urho3D #include "btMultiBodyConstraintSolver.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -27,17 +26,21 @@ subject to the following restrictions: btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) { - btScalar val = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); //solve featherstone non-contact constraints //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size()); + for (int j=0;jsetPosUpdated(false); if(constraint.m_multiBodyB) @@ -48,9 +51,15 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl for (int j=0;jsetPosUpdated(false); if(constraint.m_multiBodyB) @@ -70,7 +79,8 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl { frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse); frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse; - resolveSingleConstraintRowGeneric(frictionConstraint); + btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint); + leastSquaredResidual += residual*residual; if(frictionConstraint.m_multiBodyA) frictionConstraint.m_multiBodyA->setPosUpdated(false); @@ -79,7 +89,7 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl } } } - return val; + return leastSquaredResidual; } btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) @@ -111,7 +121,7 @@ void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar im m_data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse; } -void btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c) +btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c) { btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; @@ -124,7 +134,7 @@ void btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMult if (c.m_multiBodyA) { - ndofA = (c.m_multiBodyA->isMultiDof() ? c.m_multiBodyA->getNumDofs() : c.m_multiBodyA->getNumLinks()) + 6; + ndofA = c.m_multiBodyA->getNumDofs() + 6; for (int i = 0; i < ndofA; ++i) deltaVelADotn += m_data.m_jacobians[c.m_jacAindex+i] * m_data.m_deltaVelocities[c.m_deltaVelAindex+i]; } else if(c.m_solverBodyIdA >= 0) @@ -135,7 +145,7 @@ void btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMult if (c.m_multiBodyB) { - ndofB = (c.m_multiBodyB->isMultiDof() ? c.m_multiBodyB->getNumDofs() : c.m_multiBodyB->getNumLinks()) + 6; + ndofB = c.m_multiBodyB->getNumDofs() + 6; for (int i = 0; i < ndofB; ++i) deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex+i] * m_data.m_deltaVelocities[c.m_deltaVelBindex+i]; } else if(c.m_solverBodyIdB >= 0) @@ -170,10 +180,7 @@ void btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMult #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity - if(c.m_multiBodyA->isMultiDof()) - c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse); - else - c.m_multiBodyA->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse); + c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse); #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS } else if(c.m_solverBodyIdA >= 0) { @@ -186,73 +193,16 @@ void btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMult #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity - if(c.m_multiBodyB->isMultiDof()) - c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse); - else - c.m_multiBodyB->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse); + c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse); #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS } else if(c.m_solverBodyIdB >= 0) { bodyB->internalApplyImpulse(c.m_contactNormal2*bodyB->internalGetInvMass(),c.m_angularComponentB,deltaImpulse); } - + return deltaImpulse; } -void btMultiBodyConstraintSolver::resolveSingleConstraintRowGenericMultiBody(const btMultiBodySolverConstraint& c) -{ - - btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; - btScalar deltaVelADotn=0; - btScalar deltaVelBDotn=0; - int ndofA=0; - int ndofB=0; - - if (c.m_multiBodyA) - { - ndofA = (c.m_multiBodyA->isMultiDof() ? c.m_multiBodyA->getNumDofs() : c.m_multiBodyA->getNumLinks()) + 6; - for (int i = 0; i < ndofA; ++i) - deltaVelADotn += m_data.m_jacobians[c.m_jacAindex+i] * m_data.m_deltaVelocities[c.m_deltaVelAindex+i]; - } - - if (c.m_multiBodyB) - { - ndofB = (c.m_multiBodyB->isMultiDof() ? c.m_multiBodyB->getNumDofs() : c.m_multiBodyB->getNumLinks()) + 6; - for (int i = 0; i < ndofB; ++i) - deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex+i] * m_data.m_deltaVelocities[c.m_deltaVelBindex+i]; - } - - - deltaImpulse -= deltaVelADotn*c.m_jacDiagABInv;//m_jacDiagABInv = 1./denom - deltaImpulse -= deltaVelBDotn*c.m_jacDiagABInv; - const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; - - if (sum < c.m_lowerLimit) - { - deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; - c.m_appliedImpulse = c.m_lowerLimit; - } - else if (sum > c.m_upperLimit) - { - deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; - c.m_appliedImpulse = c.m_upperLimit; - } - else - { - c.m_appliedImpulse = sum; - } - - if (c.m_multiBodyA) - { - applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse,c.m_deltaVelAindex,ndofA); - c.m_multiBodyA->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse); - } - if (c.m_multiBodyB) - { - applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse,c.m_deltaVelBindex,ndofB); - c.m_multiBodyB->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse); - } -} void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, @@ -283,9 +233,38 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol if (bodyB) rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); - relaxation = 1.f; - + relaxation = infoGlobal.m_sor; + btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep; + + //cfm = 1 / ( dt * kp + kd ) + //erp = dt * kp / ( dt * kp + kd ) + + btScalar cfm = infoGlobal.m_globalCfm; + btScalar erp = infoGlobal.m_erp2; + + if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)) + { + if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) + cfm = cp.m_contactCFM; + if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP) + erp = cp.m_contactERP; + } else + { + if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING) + { + btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 ); + if (denom < SIMD_EPSILON) + { + denom = SIMD_EPSILON; + } + cfm = btScalar(1) / denom; + erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom; + } + } + + cfm *= invTimeStep; + if (multiBodyA) @@ -297,7 +276,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol { rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin(); } - const int ndofA = (multiBodyA->isMultiDof() ? multiBodyA->getNumDofs() : multiBodyA->getNumLinks()) + 6; + const int ndofA = multiBodyA->getNumDofs() + 6; solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId(); @@ -317,15 +296,9 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size()); btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex]; - if(multiBodyA->isMultiDof()) - multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); - else - multiBodyA->fillContactJacobian(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); + multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; - if(multiBodyA->isMultiDof()) - multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v); - else - multiBodyA->calcAccelerationDeltas(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v); + multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v); btVector3 torqueAxis0 = rel_pos1.cross(contactNormal); solverConstraint.m_relpos1CrossNormal = torqueAxis0; @@ -350,7 +323,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin(); } - const int ndofB = (multiBodyB->isMultiDof() ? multiBodyB->getNumDofs() : multiBodyB->getNumLinks()) + 6; + const int ndofB = multiBodyB->getNumDofs() + 6; solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId(); if (solverConstraint.m_deltaVelBindex <0) @@ -366,14 +339,8 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB); btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size()); - if(multiBodyB->isMultiDof()) - multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); - else - multiBodyB->fillContactJacobian(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); - if(multiBodyB->isMultiDof()) - multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v); - else - multiBodyB->calcAccelerationDeltas(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v); + multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); + multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v); btVector3 torqueAxis1 = rel_pos2.cross(contactNormal); solverConstraint.m_relpos2CrossNormal = -torqueAxis1; @@ -400,7 +367,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol int ndofA = 0; if (multiBodyA) { - ndofA = (multiBodyA->isMultiDof() ? multiBodyA->getNumDofs() : multiBodyA->getNumLinks()) + 6; + ndofA = multiBodyA->getNumDofs() + 6; jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex]; lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; for (int i = 0; i < ndofA; ++i) @@ -419,7 +386,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol } if (multiBodyB) { - const int ndofB = (multiBodyB->isMultiDof() ? multiBodyB->getNumDofs() : multiBodyB->getNumLinks()) + 6; + const int ndofB = multiBodyB->getNumDofs() + 6; jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex]; lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; for (int i = 0; i < ndofB; ++i) @@ -440,7 +407,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol - btScalar d = denom0+denom1; + btScalar d = denom0+denom1+cfm; if (d>SIMD_EPSILON) { solverConstraint.m_jacDiagABInv = relaxation/(d); @@ -468,7 +435,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol btVector3 vel1,vel2; if (multiBodyA) { - ndofA = (multiBodyA->isMultiDof() ? multiBodyA->getNumDofs() : multiBodyA->getNumLinks()) + 6; + ndofA = multiBodyA->getNumDofs() + 6; btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex]; for (int i = 0; i < ndofA ; ++i) rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; @@ -476,12 +443,14 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol { if (rb0) { - rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1); + rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) + + (rb0->getTotalTorque()*rb0->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos1)+ + rb0->getTotalForce()*rb0->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal1); } } if (multiBodyB) { - ndofB = (multiBodyB->isMultiDof() ? multiBodyB->getNumDofs() : multiBodyB->getNumLinks()) + 6; + ndofB = multiBodyB->getNumDofs() + 6; btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex]; for (int i = 0; i < ndofB ; ++i) rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; @@ -490,7 +459,9 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol { if (rb1) { - rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2); + rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2)+ + (rb1->getTotalTorque()*rb1->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos2) + + rb1->getTotalForce()*rb1->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal2); } } @@ -519,10 +490,8 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol { btScalar impulse = solverConstraint.m_appliedImpulse; btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; - if(multiBodyA->isMultiDof()) - multiBodyA->applyDeltaVeeMultiDof(deltaV,impulse); - else - multiBodyA->applyDeltaVee(deltaV,impulse); + multiBodyA->applyDeltaVeeMultiDof(deltaV,impulse); + applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA); } else { @@ -533,10 +502,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol { btScalar impulse = solverConstraint.m_appliedImpulse; btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; - if(multiBodyB->isMultiDof()) - multiBodyB->applyDeltaVeeMultiDof(deltaV,impulse); - else - multiBodyB->applyDeltaVee(deltaV,impulse); + multiBodyB->applyDeltaVeeMultiDof(deltaV,impulse); applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB); } else { @@ -556,12 +522,6 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol btScalar positionalError = 0.f; btScalar velocityError = restitution - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction - btScalar erp = infoGlobal.m_erp2; - if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) - { - erp = infoGlobal.m_erp; - } - if (penetration>0) { positionalError = 0; @@ -577,19 +537,20 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol if(!isFriction) { - if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) { //combine position and velocity into rhs solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; solverConstraint.m_rhsPenetration = 0.f; - } else + } + /*else { //split position and velocity into rhs and m_rhsPenetration solverConstraint.m_rhs = velocityImpulse; solverConstraint.m_rhsPenetration = penetrationImpulse; } - + */ solverConstraint.m_lowerLimit = 0; solverConstraint.m_upperLimit = 1e10f; } @@ -601,13 +562,282 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol solverConstraint.m_upperLimit = solverConstraint.m_friction; } - solverConstraint.m_cfm = 0.f; //why not use cfmSlip? - } + solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv; + -} + } +} +void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint, + const btVector3& constraintNormal, + btManifoldPoint& cp, + btScalar combinedTorsionalFriction, + const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + bool isFriction, btScalar desiredVelocity, btScalar cfmSlip) +{ + + BT_PROFILE("setupMultiBodyRollingFrictionConstraint"); + btVector3 rel_pos1; + btVector3 rel_pos2; + + btMultiBody* multiBodyA = solverConstraint.m_multiBodyA; + btMultiBody* multiBodyB = solverConstraint.m_multiBodyB; + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA]; + btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB]; + + btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody; + btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody; + + if (bodyA) + rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); + if (bodyB) + rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); + + relaxation = infoGlobal.m_sor; + + // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep; + + + if (multiBodyA) + { + if (solverConstraint.m_linkA<0) + { + rel_pos1 = pos1 - multiBodyA->getBasePos(); + } else + { + rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin(); + } + const int ndofA = multiBodyA->getNumDofs() + 6; + + solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId(); + + if (solverConstraint.m_deltaVelAindex <0) + { + solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size(); + multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex); + m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofA); + } else + { + btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA); + } + + solverConstraint.m_jacAindex = m_data.m_jacobians.size(); + m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofA); + m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofA); + btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size()); + + btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex]; + multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0,0,0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); + btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v); + + btVector3 torqueAxis0 = constraintNormal; + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + solverConstraint.m_contactNormal1 = btVector3(0,0,0); + } else + { + btVector3 torqueAxis0 = constraintNormal; + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + solverConstraint.m_contactNormal1 = btVector3(0,0,0); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + } + + + + if (multiBodyB) + { + if (solverConstraint.m_linkB<0) + { + rel_pos2 = pos2 - multiBodyB->getBasePos(); + } else + { + rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin(); + } + + const int ndofB = multiBodyB->getNumDofs() + 6; + + solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId(); + if (solverConstraint.m_deltaVelBindex <0) + { + solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size(); + multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex); + m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofB); + } + + solverConstraint.m_jacBindex = m_data.m_jacobians.size(); + + m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofB); + m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB); + btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size()); + + multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0,0,0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); + multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v); + + btVector3 torqueAxis1 = constraintNormal; + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + solverConstraint.m_contactNormal2 = -btVector3(0,0,0); + + } else + { + btVector3 torqueAxis1 = constraintNormal; + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + solverConstraint.m_contactNormal2 = -btVector3(0,0,0); + + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + } + + { + + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + btScalar* jacB = 0; + btScalar* jacA = 0; + btScalar* lambdaA =0; + btScalar* lambdaB =0; + int ndofA = 0; + if (multiBodyA) + { + ndofA = multiBodyA->getNumDofs() + 6; + jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex]; + lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA; ++i) + { + btScalar j = jacA[i] ; + btScalar l =lambdaA[i]; + denom0 += j*l; + } + } else + { + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + constraintNormal.dot(vec); + } + } + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumDofs() + 6; + jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex]; + lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB; ++i) + { + btScalar j = jacB[i] ; + btScalar l =lambdaB[i]; + denom1 += j*l; + } + + } else + { + if (rb1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + constraintNormal.dot(vec); + } + } + + + + btScalar d = denom0+denom1+infoGlobal.m_globalCfm; + if (d>SIMD_EPSILON) + { + solverConstraint.m_jacDiagABInv = relaxation/(d); + } else + { + //disable the constraint row to handle singularity/redundant constraint + solverConstraint.m_jacDiagABInv = 0.f; + } + + } + + + //compute rhs and remaining solverConstraint fields + + + + btScalar restitution = 0.f; + btScalar penetration = isFriction? 0 : cp.getDistance(); + + btScalar rel_vel = 0.f; + int ndofA = 0; + int ndofB = 0; + { + + btVector3 vel1,vel2; + if (multiBodyA) + { + ndofA = multiBodyA->getNumDofs() + 6; + btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA ; ++i) + rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; + } else + { + if (rb0) + { + rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1); + } + } + if (multiBodyB) + { + ndofB = multiBodyB->getNumDofs() + 6; + btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB ; ++i) + rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; + + } else + { + if (rb1) + { + rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2); + } + } + + solverConstraint.m_friction =combinedTorsionalFriction; + + if(!isFriction) + { + restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (restitution <= btScalar(0.)) + { + restitution = 0.f; + } + } + } + + + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedPushImpulse = 0.f; + + { + + btScalar velocityError = restitution - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction + + if (penetration>0) + { + velocityError -= penetration / infoGlobal.m_timeStep; + } + + btScalar velocityImpulse = velocityError*solverConstraint.m_jacDiagABInv; + + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = 0.f; + solverConstraint.m_lowerLimit = -solverConstraint.m_friction; + solverConstraint.m_upperLimit = solverConstraint.m_friction; + + solverConstraint.m_cfm = infoGlobal.m_globalCfm*solverConstraint.m_jacDiagABInv; + + + + } + +} btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) { @@ -644,6 +874,43 @@ btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionCo return solverConstraint; } +btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp, + btScalar combinedTorsionalFriction, + btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) +{ + BT_PROFILE("addMultiBodyRollingFrictionConstraint"); + btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing(); + solverConstraint.m_orgConstraint = 0; + solverConstraint.m_orgDofIndex = -1; + + solverConstraint.m_frictionIndex = frictionIndex; + bool isFriction = true; + + const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0()); + const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1()); + + btMultiBody* mbA = fcA? fcA->m_multiBody : 0; + btMultiBody* mbB = fcB? fcB->m_multiBody : 0; + + int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep); + int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep); + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_multiBodyA = mbA; + if (mbA) + solverConstraint.m_linkA = fcA->m_link; + + solverConstraint.m_multiBodyB = mbB; + if (mbB) + solverConstraint.m_linkB = fcB->m_link; + + solverConstraint.m_originalContactPoint = &cp; + + setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction,infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip); + return solverConstraint; +} + void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) { const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0()); @@ -668,8 +935,9 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* // if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero()))) // return; - - + //only a single rollingFriction per manifold + int rollingFriction=1; + for (int j=0;jgetNumContacts();j++) { @@ -710,49 +978,11 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* #define ENABLE_FRICTION #ifdef ENABLE_FRICTION solverConstraint.m_frictionIndex = frictionIndex; -#if ROLLING_FRICTION - int rollingFriction=1; - btVector3 angVelA(0,0,0),angVelB(0,0,0); - if (rb0) - angVelA = rb0->getAngularVelocity(); - if (rb1) - angVelB = rb1->getAngularVelocity(); - btVector3 relAngVel = angVelB-angVelA; - - if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0)) - { - //only a single rollingFriction per manifold - rollingFriction--; - if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold) - { - relAngVel.normalize(); - applyAnisotropicFriction(colObj0,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj1,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - if (relAngVel.length()>0.001) - addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - - } else - { - addRollingFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - btVector3 axis0,axis1; - btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1); - applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - if (axis0.length()>0.001) - addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - if (axis1.length()>0.001) - addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - - } - } -#endif //ROLLING_FRICTION ///Bullet has several options to set the friction directions - ///By default, each contact has only a single friction direction that is recomputed automatically very frame + ///By default, each contact has only a single friction direction that is recomputed automatically every frame ///based on the relative linear velocity. - ///If the relative velocity it zero, it will automatically compute a friction direction. + ///If the relative velocity is zero, it will automatically compute a friction direction. ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. @@ -764,7 +994,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) ///this will give a conveyor belt effect /// - if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED)) {/* cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); @@ -793,6 +1023,15 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal); + + if (rollingFriction > 0) + { + addMultiBodyTorsionalFrictionConstraint(cp.m_normalWorldOnB,manifold,frictionIndex,cp,cp.m_combinedSpinningFriction, colObj0,colObj1, relaxation,infoGlobal); + addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal); + addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal); + + rollingFriction--; + } if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) { @@ -803,16 +1042,16 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) { - cp.m_lateralFrictionInitialized = true; + cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; } } } else { - addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal,cp.m_contactMotion1, cp.m_contactCFM1); + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal,cp.m_contactMotion1, cp.m_frictionCFM); if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) - addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation, infoGlobal,cp.m_contactMotion2, cp.m_contactCFM2); + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation, infoGlobal,cp.m_contactMotion2, cp.m_frictionCFM); //setMultiBodyFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); //todo: @@ -888,8 +1127,7 @@ static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodyS } #endif -// Urho3D: disable include -//#include "Bullet3Common/b3Logging.h" + void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime) { #if 1 @@ -906,45 +1144,39 @@ void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolv if (c.m_multiBodyA) { - if(c.m_multiBodyA->isMultiDof()) + c.m_multiBodyA->setCompanionId(-1); + btVector3 force = c.m_contactNormal1*(c.m_appliedImpulse/deltaTime); + btVector3 torque = c.m_relpos1CrossNormal*(c.m_appliedImpulse/deltaTime); + if (c.m_linkA<0) { - c.m_multiBodyA->setCompanionId(-1); - btVector3 force = c.m_contactNormal1*(c.m_appliedImpulse/deltaTime); - btVector3 torque = c.m_relpos1CrossNormal*(c.m_appliedImpulse/deltaTime); - if (c.m_linkA<0) - { - c.m_multiBodyA->addBaseConstraintForce(force); - c.m_multiBodyA->addBaseConstraintTorque(torque); - } else - { - c.m_multiBodyA->addLinkConstraintForce(c.m_linkA,force); - //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]); - c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA,torque); - } + c.m_multiBodyA->addBaseConstraintForce(force); + c.m_multiBodyA->addBaseConstraintTorque(torque); + } else + { + c.m_multiBodyA->addLinkConstraintForce(c.m_linkA,force); + //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]); + c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA,torque); } } if (c.m_multiBodyB) { - if(c.m_multiBodyB->isMultiDof()) { + c.m_multiBodyB->setCompanionId(-1); + btVector3 force = c.m_contactNormal2*(c.m_appliedImpulse/deltaTime); + btVector3 torque = c.m_relpos2CrossNormal*(c.m_appliedImpulse/deltaTime); + if (c.m_linkB<0) + { + c.m_multiBodyB->addBaseConstraintForce(force); + c.m_multiBodyB->addBaseConstraintTorque(torque); + } else { - c.m_multiBodyB->setCompanionId(-1); - btVector3 force = c.m_contactNormal2*(c.m_appliedImpulse/deltaTime); - btVector3 torque = c.m_relpos2CrossNormal*(c.m_appliedImpulse/deltaTime); - if (c.m_linkB<0) - { - c.m_multiBodyB->addBaseConstraintForce(force); - c.m_multiBodyB->addBaseConstraintTorque(torque); - } else { - { - c.m_multiBodyB->addLinkConstraintForce(c.m_linkB,force); - //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]); - c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB,torque); - } - + c.m_multiBodyB->addLinkConstraintForce(c.m_linkB,force); + //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]); + c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB,torque); } + } } } diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h index 0ec06bf554..489347d874 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h @@ -43,12 +43,16 @@ ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpu btMultiBodyConstraint** m_tmpMultiBodyConstraints; int m_tmpNumMultiBodyConstraints; - void resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c); - void resolveSingleConstraintRowGenericMultiBody(const btMultiBodySolverConstraint& c); + btScalar resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c); + void convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal); - btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0); + + btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0); + btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp, + btScalar combinedTorsionalFriction, + btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0); void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint& constraintRow, btScalar* jacA,btScalar* jacB, @@ -60,6 +64,15 @@ ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpu btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0); + + //either rolling or spinning friction + void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint, + const btVector3& contactNormal, + btManifoldPoint& cp, + btScalar combinedTorsionalFriction, + const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0); void convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp index fa4052d46e..20b6a04b35 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp @@ -24,7 +24,7 @@ subject to the following restrictions: #include "LinearMath/btSerializer.h" -void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, short group, short mask) +void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask) { m_multiBodies.push_back(body); @@ -332,10 +332,10 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager:: } } - if (m_solverInfo->m_minimumSolverBatchSize<=1) - { - m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher); - } else + //if (m_solverInfo->m_minimumSolverBatchSize<=1) + //{ + // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher); + //} else { for (i=0;i world_to_local; - btAlignedObjectArray local_origin; for (int b=0;bforwardKinematics(world_to_local,local_origin); + bod->forwardKinematics(m_scratch_world_to_local,m_scratch_local_origin); } } void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { forwardKinematics(); - btAlignedObjectArray scratch_r; - btAlignedObjectArray scratch_v; - btAlignedObjectArray scratch_m; BT_PROFILE("solveConstraints"); @@ -463,9 +458,9 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) if (!isSleeping) { //useless? they get resized in stepVelocities once again (AND DIFFERENTLY) - scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd) - scratch_v.resize(bod->getNumLinks()+1); - scratch_m.resize(bod->getNumLinks()+1); + m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd) + m_scratch_v.resize(bod->getNumLinks()+1); + m_scratch_m.resize(bod->getNumLinks()+1); bod->addBaseForce(m_gravity * bod->getBaseMass()); @@ -500,16 +495,15 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) if (!isSleeping) { //useless? they get resized in stepVelocities once again (AND DIFFERENTLY) - scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd) - scratch_v.resize(bod->getNumLinks()+1); - scratch_m.resize(bod->getNumLinks()+1); + m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd) + m_scratch_v.resize(bod->getNumLinks()+1); + m_scratch_m.resize(bod->getNumLinks()+1); bool doNotUpdatePos = false; - if(bod->isMultiDof()) { if(!bod->isUsingRK4Integration()) { - bod->stepVelocitiesMultiDof(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m); + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m); } else { @@ -595,9 +589,9 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) // btScalar h = solverInfo.m_timeStep; - #define output &scratch_r[bod->getNumDofs()] + #define output &m_scratch_r[bod->getNumDofs()] //calc qdd0 from: q0 & qd0 - bod->stepVelocitiesMultiDof(0., scratch_r, scratch_v, scratch_m); + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m); pCopy(output, scratch_qdd0, 0, numDofs); //calc q1 = q0 + h/2 * qd0 pResetQx(); @@ -607,7 +601,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) // //calc qdd1 from: q1 & qd1 pCopyToVelocityVector(bod, scratch_qd1); - bod->stepVelocitiesMultiDof(0., scratch_r, scratch_v, scratch_m); + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m); pCopy(output, scratch_qdd1, 0, numDofs); //calc q2 = q0 + h/2 * qd1 pResetQx(); @@ -617,7 +611,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) // //calc qdd2 from: q2 & qd2 pCopyToVelocityVector(bod, scratch_qd2); - bod->stepVelocitiesMultiDof(0., scratch_r, scratch_v, scratch_m); + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m); pCopy(output, scratch_qdd2, 0, numDofs); //calc q3 = q0 + h * qd2 pResetQx(); @@ -627,7 +621,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) // //calc qdd3 from: q3 & qd3 pCopyToVelocityVector(bod, scratch_qd3); - bod->stepVelocitiesMultiDof(0., scratch_r, scratch_v, scratch_m); + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m); pCopy(output, scratch_qdd3, 0, numDofs); // @@ -662,15 +656,12 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { for(int link = 0; link < bod->getNumLinks(); ++link) bod->getLink(link).updateCacheMultiDof(); - bod->stepVelocitiesMultiDof(0, scratch_r, scratch_v, scratch_m); + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m); } } } - else//if(bod->isMultiDof()) - { - bod->stepVelocities(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m); - } + #ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY bod->clearForcesAndTorques(); #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY @@ -705,25 +696,25 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) if (!isSleeping) { //useless? they get resized in stepVelocities once again (AND DIFFERENTLY) - scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd) - scratch_v.resize(bod->getNumLinks()+1); - scratch_m.resize(bod->getNumLinks()+1); + m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd) + m_scratch_v.resize(bod->getNumLinks()+1); + m_scratch_m.resize(bod->getNumLinks()+1); - if(bod->isMultiDof()) + + { + if(!bod->isUsingRK4Integration()) { - if(!bod->isUsingRK4Integration()) - { - bool isConstraintPass = true; - bod->stepVelocitiesMultiDof(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m, isConstraintPass); - } + bool isConstraintPass = true; + bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass); + } } } } } for (int i=0;im_multiBodies.size();i++) - { - btMultiBody* bod = m_multiBodies[i]; + { + btMultiBody* bod = m_multiBodies[i]; bod->processDeltaVeeMultiDof2(); } @@ -736,9 +727,7 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep) { BT_PROFILE("btMultiBody stepPositions"); //integrate and update the Featherstone hierarchies - btAlignedObjectArray world_to_local; - btAlignedObjectArray local_origin; - + for (int b=0;bisMultiDof()) + { if(!bod->isPosUpdated()) bod->stepPositionsMultiDof(timeStep); @@ -773,14 +762,11 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep) bod->setPosUpdated(false); } } - else - { - bod->stepPositions(timeStep); - } - world_to_local.resize(nLinks+1); - local_origin.resize(nLinks+1); + + m_scratch_world_to_local.resize(nLinks+1); + m_scratch_local_origin.resize(nLinks+1); - bod->updateCollisionObjectWorldTransforms(world_to_local,local_origin); + bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local,m_scratch_local_origin); } else { @@ -825,8 +811,6 @@ void btMultiBodyDynamicsWorld::debugDrawWorld() { BT_PROFILE("btMultiBody debugDrawWorld"); - btAlignedObjectArray world_to_local1; - btAlignedObjectArray local_origin1; for (int c=0;cforwardKinematics(world_to_local1,local_origin1); + bod->forwardKinematics(m_scratch_world_to_local1,m_scratch_local_origin1); getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h index 03ef3335c2..e5113ae6c5 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h @@ -36,6 +36,16 @@ class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld btMultiBodyConstraintSolver* m_multiBodyConstraintSolver; MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback; + //cached data to avoid memory allocations + btAlignedObjectArray m_scratch_world_to_local; + btAlignedObjectArray m_scratch_local_origin; + btAlignedObjectArray m_scratch_world_to_local1; + btAlignedObjectArray m_scratch_local_origin1; + btAlignedObjectArray m_scratch_r; + btAlignedObjectArray m_scratch_v; + btAlignedObjectArray m_scratch_m; + + virtual void calculateSimulationIslands(); virtual void updateActivationState(btScalar timeStep); virtual void solveConstraints(btContactSolverInfo& solverInfo); @@ -48,7 +58,7 @@ class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld virtual ~btMultiBodyDynamicsWorld (); - virtual void addMultiBody(btMultiBody* body, short group= btBroadphaseProxy::DefaultFilter, short mask=btBroadphaseProxy::AllFilter); + virtual void addMultiBody(btMultiBody* body, int group= btBroadphaseProxy::DefaultFilter, int mask=btBroadphaseProxy::AllFilter); virtual void removeMultiBody(btMultiBody* body); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp new file mode 100644 index 0000000000..6ca5b8b0d8 --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp @@ -0,0 +1,211 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without 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. +*/ + +///This file was written by Erwin Coumans + +#include "btMultiBodyFixedConstraint.h" +#include "btMultiBodyLinkCollider.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h" +#include "LinearMath/btIDebugDraw.h" + +#define BTMBFIXEDCONSTRAINT_DIM 6 + +btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB) + :btMultiBodyConstraint(body,0,link,-1,BTMBFIXEDCONSTRAINT_DIM,false), + m_rigidBodyA(0), + m_rigidBodyB(bodyB), + m_pivotInA(pivotInA), + m_pivotInB(pivotInB), + m_frameInA(frameInA), + m_frameInB(frameInB) +{ + m_data.resize(BTMBFIXEDCONSTRAINT_DIM);//at least store the applied impulses +} + +btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB) + :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBFIXEDCONSTRAINT_DIM,false), + m_rigidBodyA(0), + m_rigidBodyB(0), + m_pivotInA(pivotInA), + m_pivotInB(pivotInB), + m_frameInA(frameInA), + m_frameInB(frameInB) +{ + m_data.resize(BTMBFIXEDCONSTRAINT_DIM);//at least store the applied impulses +} + +void btMultiBodyFixedConstraint::finalizeMultiDof() +{ + //not implemented yet + btAssert(0); +} + +btMultiBodyFixedConstraint::~btMultiBodyFixedConstraint() +{ +} + + +int btMultiBodyFixedConstraint::getIslandIdA() const +{ + if (m_rigidBodyA) + return m_rigidBodyA->getIslandTag(); + + if (m_bodyA) + { + btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider(); + if (col) + return col->getIslandTag(); + for (int i=0;igetNumLinks();i++) + { + if (m_bodyA->getLink(i).m_collider) + return m_bodyA->getLink(i).m_collider->getIslandTag(); + } + } + return -1; +} + +int btMultiBodyFixedConstraint::getIslandIdB() const +{ + if (m_rigidBodyB) + return m_rigidBodyB->getIslandTag(); + if (m_bodyB) + { + btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider(); + if (col) + return col->getIslandTag(); + + for (int i=0;igetNumLinks();i++) + { + col = m_bodyB->getLink(i).m_collider; + if (col) + return col->getIslandTag(); + } + } + return -1; +} + +void btMultiBodyFixedConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal) +{ + int numDim = BTMBFIXEDCONSTRAINT_DIM; + for (int i=0;igetCompanionId(); + pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA; + frameAworld = frameAworld.transpose()*btMatrix3x3(m_rigidBodyA->getOrientation()); + + } else + { + if (m_bodyA) { + pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA); + frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld); + } + } + btVector3 pivotBworld = m_pivotInB; + btMatrix3x3 frameBworld = m_frameInB; + if (m_rigidBodyB) + { + constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId(); + pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB; + frameBworld = frameBworld.transpose()*btMatrix3x3(m_rigidBodyB->getOrientation()); + + } else + { + if (m_bodyB) { + pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB); + frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld); + } + } + + btMatrix3x3 relRot = frameAworld.inverse()*frameBworld; + btVector3 angleDiff; + btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot,angleDiff); + + btVector3 constraintNormalLin(0,0,0); + btVector3 constraintNormalAng(0,0,0); + btScalar posError = 0.0; + if (i < 3) { + constraintNormalLin[i] = -1; + posError = (pivotAworld-pivotBworld).dot(constraintNormalLin); + fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng, + constraintNormalLin, pivotAworld, pivotBworld, + posError, + infoGlobal, + -m_maxAppliedImpulse, m_maxAppliedImpulse + ); + } + else { //i>=3 + constraintNormalAng = frameAworld.getColumn(i%3); + posError = angleDiff[i%3]; + fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng, + constraintNormalLin, pivotAworld, pivotBworld, + posError, + infoGlobal, + -m_maxAppliedImpulse, m_maxAppliedImpulse, true + ); + } + } +} + +void btMultiBodyFixedConstraint::debugDraw(class btIDebugDraw* drawer) +{ + btTransform tr; + tr.setIdentity(); + + if (m_rigidBodyA) + { + btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA; + tr.setOrigin(pivot); + drawer->drawTransform(tr, 0.1); + } + if (m_bodyA) + { + btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA); + tr.setOrigin(pivotAworld); + drawer->drawTransform(tr, 0.1); + } + if (m_rigidBodyB) + { + // that ideally should draw the same frame + btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB; + tr.setOrigin(pivot); + drawer->drawTransform(tr, 0.1); + } + if (m_bodyB) + { + btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB); + tr.setOrigin(pivotBworld); + drawer->drawTransform(tr, 0.1); + } +} diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h new file mode 100644 index 0000000000..036025136e --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h @@ -0,0 +1,94 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without 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. +*/ + +///This file was written by Erwin Coumans + +#ifndef BT_MULTIBODY_FIXED_CONSTRAINT_H +#define BT_MULTIBODY_FIXED_CONSTRAINT_H + +#include "btMultiBodyConstraint.h" + +class btMultiBodyFixedConstraint : public btMultiBodyConstraint +{ +protected: + + btRigidBody* m_rigidBodyA; + btRigidBody* m_rigidBodyB; + btVector3 m_pivotInA; + btVector3 m_pivotInB; + btMatrix3x3 m_frameInA; + btMatrix3x3 m_frameInB; + +public: + + btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB); + btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB); + + virtual ~btMultiBodyFixedConstraint(); + + virtual void finalizeMultiDof(); + + virtual int getIslandIdA() const; + virtual int getIslandIdB() const; + + virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal); + + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + void setPivotInA(const btVector3& pivotInA) + { + m_pivotInA = pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } + + virtual void setPivotInB(const btVector3& pivotInB) + { + m_pivotInB = pivotInB; + } + + const btMatrix3x3& getFrameInA() const + { + return m_frameInA; + } + + void setFrameInA(const btMatrix3x3& frameInA) + { + m_frameInA = frameInA; + } + + const btMatrix3x3& getFrameInB() const + { + return m_frameInB; + } + + virtual void setFrameInB(const btMatrix3x3& frameInB) + { + m_frameInB = frameInB; + } + + virtual void debugDraw(class btIDebugDraw* drawer); + +}; + +#endif //BT_MULTIBODY_FIXED_CONSTRAINT_H diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp index b2d8641391..7078176738 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp @@ -38,7 +38,7 @@ void btMultiBodyJointLimitConstraint::finalizeMultiDof() allocateJacobiansMultiDof(); - unsigned int offset = 6 + (m_bodyA->isMultiDof() ? m_bodyA->getLink(m_linkA).m_dofOffset : m_linkA); + unsigned int offset = 6 + m_bodyA->getLink(m_linkA).m_dofOffset; // row 0: the lower bound jacobianA(0)[offset] = 1; @@ -122,9 +122,8 @@ void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraint const btScalar posError = 0; //why assume it's zero? const btVector3 dummy(0, 0, 0); - btScalar rel_vel = fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,posError,infoGlobal,0,m_maxAppliedImpulse); + btScalar rel_vel = fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,0,m_maxAppliedImpulse); - if (m_bodyA->isMultiDof()) { //expect either prismatic or revolute joint type for now btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic)); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp index 4f501f1322..2a88d806e2 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp @@ -23,7 +23,12 @@ subject to the following restrictions: btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse) :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,1,true), - m_desiredVelocity(desiredVelocity) + m_desiredVelocity(desiredVelocity), + m_desiredPosition(0), + m_kd(1.), + m_kp(0), + m_erp(1), + m_rhsClamp(SIMD_INFINITY) { m_maxAppliedImpulse = maxMotorImpulse; @@ -39,7 +44,7 @@ void btMultiBodyJointMotor::finalizeMultiDof() // note: we rely on the fact that data.m_jacobians are // always initialized to zero by the Constraint ctor int linkDoF = 0; - unsigned int offset = 6 + (m_bodyA->isMultiDof() ? m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF : m_linkA); + unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF); // row 0: the lower bound // row 0: the lower bound @@ -51,7 +56,12 @@ void btMultiBodyJointMotor::finalizeMultiDof() btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse) //:btMultiBodyConstraint(body,0,link,-1,1,true), :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,1,true), - m_desiredVelocity(desiredVelocity) + m_desiredVelocity(desiredVelocity), + m_desiredPosition(0), + m_kd(1.), + m_kp(0), + m_erp(1), + m_rhsClamp(SIMD_INFINITY) { btAssert(linkDoF < body->getLink(link).m_dofCount); @@ -114,11 +124,26 @@ void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& con { btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing(); - - fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,1,false,m_desiredVelocity); + int dof = 0; + btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof]; + btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof]; + btScalar positionStabiliationTerm = m_erp*(m_desiredPosition-currentPosition)/infoGlobal.m_timeStep; + + btScalar velocityError = (m_desiredVelocity - currentVelocity); + btScalar rhs = m_kp * positionStabiliationTerm + currentVelocity+m_kd * velocityError; + if (rhs>m_rhsClamp) + { + rhs=m_rhsClamp; + } + if (rhs<-m_rhsClamp) + { + rhs=-m_rhsClamp; + } + + + fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,false,1,false,rhs); constraintRow.m_orgConstraint = this; constraintRow.m_orgDofIndex = row; - if (m_bodyA->isMultiDof()) { //expect either prismatic or revolute joint type for now btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic)); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h index 011aadcfa4..4063bed79a 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h @@ -25,8 +25,13 @@ class btMultiBodyJointMotor : public btMultiBodyConstraint { protected: - btScalar m_desiredVelocity; + btScalar m_desiredPosition; + btScalar m_kd; + btScalar m_kp; + btScalar m_erp; + btScalar m_rhsClamp;//maximum error + public: @@ -42,11 +47,30 @@ class btMultiBodyJointMotor : public btMultiBodyConstraint btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal); - virtual void setVelocityTarget(btScalar velTarget) + virtual void setVelocityTarget(btScalar velTarget, btScalar kd = 1.f) { m_desiredVelocity = velTarget; + m_kd = kd; } + virtual void setPositionTarget(btScalar posTarget, btScalar kp = 1.f) + { + m_desiredPosition = posTarget; + m_kp = kp; + } + + virtual void setErp(btScalar erp) + { + m_erp = erp; + } + virtual btScalar getErp() const + { + return m_erp; + } + virtual void setRhsClamp(btScalar rhsClamp) + { + m_rhsClamp = rhsClamp; + } virtual void debugDraw(class btIDebugDraw* drawer) { //todo(erwincoumans) diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h index e167573824..a259611169 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h @@ -132,8 +132,12 @@ btVector3 m_appliedConstraintForce; // In WORLD frame const char* m_linkName;//m_linkName memory needs to be managed by the developer/user! const char* m_jointName;//m_jointName memory needs to be managed by the developer/user! + const void* m_userPtr;//m_userPtr ptr needs to be managed by the developer/user! + + btScalar m_jointDamping; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping. + btScalar m_jointFriction; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor. - // ctor: set some sensible defaults + // ctor: set some sensible defaults btMultibodyLink() : m_mass(1), m_parent(-1), @@ -146,7 +150,10 @@ btVector3 m_appliedConstraintForce; // In WORLD frame m_jointType(btMultibodyLink::eInvalid), m_jointFeedback(0), m_linkName(0), - m_jointName(0) + m_jointName(0), + m_userPtr(0), + m_jointDamping(0), + m_jointFriction(0) { m_inertiaLocal.setValue(1, 1, 1); @@ -165,20 +172,6 @@ btVector3 m_appliedConstraintForce; // In WORLD frame } // routine to update m_cachedRotParentToThis and m_cachedRVector - void updateCache() - { - //multidof - if (m_jointType == eRevolute) - { - m_cachedRotParentToThis = btQuaternion(getAxisTop(0),-m_jointPos[0]) * m_zeroRotParentToThis; - m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis,m_eVector); - } else - { - // m_cachedRotParentToThis never changes, so no need to update - m_cachedRVector = m_eVector + m_jointPos[0] * getAxisBottom(0); - } - } - void updateCacheMultiDof(btScalar *pq = 0) { btScalar *pJointPos = (pq ? pq : &m_jointPos[0]); diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp index 12b21f7460..125d52ad0b 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp @@ -159,7 +159,7 @@ int numDim = BTMBP2PCONSTRAINT_DIM; #ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST - fillMultiBodyConstraint(constraintRow, data, 0, 0, + fillMultiBodyConstraint(constraintRow, data, 0, 0, btVector3(0,0,0), contactNormalOnB, pivotAworld, pivotBworld, //sucks but let it be this way "for the time being" posError, infoGlobal, diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h index b2e219ac15..bf39acc5b9 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h @@ -22,7 +22,7 @@ subject to the following restrictions: //#define BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST -class btMultiBodyPoint2Point : public btMultiBodyConstraint +ATTRIBUTE_ALIGNED16(class) btMultiBodyPoint2Point : public btMultiBodyConstraint { protected: @@ -34,6 +34,8 @@ class btMultiBodyPoint2Point : public btMultiBodyConstraint public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB); btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB); @@ -53,11 +55,12 @@ class btMultiBodyPoint2Point : public btMultiBodyConstraint return m_pivotInB; } - void setPivotInB(const btVector3& pivotInB) + virtual void setPivotInB(const btVector3& pivotInB) { m_pivotInB = pivotInB; } + virtual void debugDraw(class btIDebugDraw* drawer); }; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp new file mode 100644 index 0000000000..3b64b8183f --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp @@ -0,0 +1,230 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without 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. +*/ + +///This file was written by Erwin Coumans + +#include "btMultiBodySliderConstraint.h" +#include "btMultiBodyLinkCollider.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h" +#include "LinearMath/btIDebugDraw.h" + +#define BTMBSLIDERCONSTRAINT_DIM 5 +#define EPSILON 0.000001 + +btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis) + :btMultiBodyConstraint(body,0,link,-1,BTMBSLIDERCONSTRAINT_DIM,false), + m_rigidBodyA(0), + m_rigidBodyB(bodyB), + m_pivotInA(pivotInA), + m_pivotInB(pivotInB), + m_frameInA(frameInA), + m_frameInB(frameInB), + m_jointAxis(jointAxis) +{ + m_data.resize(BTMBSLIDERCONSTRAINT_DIM);//at least store the applied impulses +} + +btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis) + :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBSLIDERCONSTRAINT_DIM,false), + m_rigidBodyA(0), + m_rigidBodyB(0), + m_pivotInA(pivotInA), + m_pivotInB(pivotInB), + m_frameInA(frameInA), + m_frameInB(frameInB), + m_jointAxis(jointAxis) +{ + m_data.resize(BTMBSLIDERCONSTRAINT_DIM);//at least store the applied impulses +} + +void btMultiBodySliderConstraint::finalizeMultiDof() +{ + //not implemented yet + btAssert(0); +} + +btMultiBodySliderConstraint::~btMultiBodySliderConstraint() +{ +} + + +int btMultiBodySliderConstraint::getIslandIdA() const +{ + if (m_rigidBodyA) + return m_rigidBodyA->getIslandTag(); + + if (m_bodyA) + { + btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider(); + if (col) + return col->getIslandTag(); + for (int i=0;igetNumLinks();i++) + { + if (m_bodyA->getLink(i).m_collider) + return m_bodyA->getLink(i).m_collider->getIslandTag(); + } + } + return -1; +} + +int btMultiBodySliderConstraint::getIslandIdB() const +{ + if (m_rigidBodyB) + return m_rigidBodyB->getIslandTag(); + if (m_bodyB) + { + btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider(); + if (col) + return col->getIslandTag(); + + for (int i=0;igetNumLinks();i++) + { + col = m_bodyB->getLink(i).m_collider; + if (col) + return col->getIslandTag(); + } + } + return -1; +} + +void btMultiBodySliderConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal) +{ + // Convert local points back to world + btVector3 pivotAworld = m_pivotInA; + btMatrix3x3 frameAworld = m_frameInA; + btVector3 jointAxis = m_jointAxis; + if (m_rigidBodyA) + { + pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA; + frameAworld = m_frameInA.transpose()*btMatrix3x3(m_rigidBodyA->getOrientation()); + jointAxis = quatRotate(m_rigidBodyA->getOrientation(),m_jointAxis); + + } else if (m_bodyA) { + pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA); + frameAworld = m_bodyA->localFrameToWorld(m_linkA, m_frameInA); + jointAxis = m_bodyA->localDirToWorld(m_linkA, m_jointAxis); + } + btVector3 pivotBworld = m_pivotInB; + btMatrix3x3 frameBworld = m_frameInB; + if (m_rigidBodyB) + { + pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB; + frameBworld = m_frameInB.transpose()*btMatrix3x3(m_rigidBodyB->getOrientation()); + + } else if (m_bodyB) { + pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB); + frameBworld = m_bodyB->localFrameToWorld(m_linkB, m_frameInB); + } + + btVector3 constraintAxis[2]; + for (int i = 0; i < 3; ++i) + { + constraintAxis[0] = frameAworld.getColumn(i).cross(jointAxis); + if (constraintAxis[0].safeNorm() > EPSILON) + { + constraintAxis[0] = constraintAxis[0].normalized(); + constraintAxis[1] = jointAxis.cross(constraintAxis[0]); + constraintAxis[1] = constraintAxis[1].normalized(); + break; + } + } + + btMatrix3x3 relRot = frameAworld.inverse()*frameBworld; + btVector3 angleDiff; + btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot,angleDiff); + + int numDim = BTMBSLIDERCONSTRAINT_DIM; + for (int i=0;igetCompanionId(); + } + if (m_rigidBodyB) + { + constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId(); + } + + btVector3 constraintNormalLin(0,0,0); + btVector3 constraintNormalAng(0,0,0); + btScalar posError = 0.0; + if (i < 2) { + constraintNormalLin = constraintAxis[i]; + posError = (pivotAworld-pivotBworld).dot(constraintNormalLin); + fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng, + constraintNormalLin, pivotAworld, pivotBworld, + posError, + infoGlobal, + -m_maxAppliedImpulse, m_maxAppliedImpulse + ); + } + else { //i>=2 + constraintNormalAng = frameAworld.getColumn(i%3); + posError = angleDiff[i%3]; + fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng, + constraintNormalLin, pivotAworld, pivotBworld, + posError, + infoGlobal, + -m_maxAppliedImpulse, m_maxAppliedImpulse, true + ); + } + } +} + +void btMultiBodySliderConstraint::debugDraw(class btIDebugDraw* drawer) +{ + btTransform tr; + tr.setIdentity(); + + if (m_rigidBodyA) + { + btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA; + tr.setOrigin(pivot); + drawer->drawTransform(tr, 0.1); + } + if (m_bodyA) + { + btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA); + tr.setOrigin(pivotAworld); + drawer->drawTransform(tr, 0.1); + } + if (m_rigidBodyB) + { + // that ideally should draw the same frame + btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB; + tr.setOrigin(pivot); + drawer->drawTransform(tr, 0.1); + } + if (m_bodyB) + { + btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB); + tr.setOrigin(pivotBworld); + drawer->drawTransform(tr, 0.1); + } +} diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h new file mode 100644 index 0000000000..0a6cf3df12 --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h @@ -0,0 +1,105 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without 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. +*/ + +///This file was written by Erwin Coumans + +#ifndef BT_MULTIBODY_SLIDER_CONSTRAINT_H +#define BT_MULTIBODY_SLIDER_CONSTRAINT_H + +#include "btMultiBodyConstraint.h" + +class btMultiBodySliderConstraint : public btMultiBodyConstraint +{ +protected: + + btRigidBody* m_rigidBodyA; + btRigidBody* m_rigidBodyB; + btVector3 m_pivotInA; + btVector3 m_pivotInB; + btMatrix3x3 m_frameInA; + btMatrix3x3 m_frameInB; + btVector3 m_jointAxis; + +public: + + btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis); + btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis); + + virtual ~btMultiBodySliderConstraint(); + + virtual void finalizeMultiDof(); + + virtual int getIslandIdA() const; + virtual int getIslandIdB() const; + + virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal); + + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + void setPivotInA(const btVector3& pivotInA) + { + m_pivotInA = pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } + + virtual void setPivotInB(const btVector3& pivotInB) + { + m_pivotInB = pivotInB; + } + + const btMatrix3x3& getFrameInA() const + { + return m_frameInA; + } + + void setFrameInA(const btMatrix3x3& frameInA) + { + m_frameInA = frameInA; + } + + const btMatrix3x3& getFrameInB() const + { + return m_frameInB; + } + + virtual void setFrameInB(const btMatrix3x3& frameInB) + { + m_frameInB = frameInB; + } + + const btVector3& getJointAxis() const + { + return m_jointAxis; + } + + void setJointAxis(const btVector3& jointAxis) + { + m_jointAxis = jointAxis; + } + + virtual void debugDraw(class btIDebugDraw* drawer); + +}; + +#endif //BT_MULTIBODY_SLIDER_CONSTRAINT_H diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp index 6688694a92..8f54c52626 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp @@ -22,8 +22,7 @@ subject to the following restrictions: btMLCPSolver::btMLCPSolver( btMLCPSolverInterface* solver) :m_solver(solver), -m_fallback(0), -m_cfm(0.000001)//0.0000001 +m_fallback(0) { } @@ -216,12 +215,12 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal) jointNodeArray.reserve(2*m_allConstraintPtrArray.size()); } - static btMatrixXu J3; + btMatrixXu& J3 = m_scratchJ3; { BT_PROFILE("J3.resize"); J3.resize(2*m,8); } - static btMatrixXu JinvM3; + btMatrixXu& JinvM3 = m_scratchJInvM3; { BT_PROFILE("JinvM3.resize/setZero"); @@ -231,7 +230,7 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal) } int cur=0; int rowOffset = 0; - static btAlignedObjectArray ofs; + btAlignedObjectArray& ofs = m_scratchOfs; { BT_PROFILE("ofs resize"); ofs.resize(0); @@ -436,7 +435,7 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal) // add cfm to the diagonal of m_A for ( int i=0; igetInvInertiaTensorWorld()[r][c] : 0); } - static btMatrixXu J; + btMatrixXu& J = m_scratchJ; J.resize(numConstraintRows,6*numBodies); J.setZero(); @@ -542,10 +541,10 @@ void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal) } } - static btMatrixXu J_transpose; + btMatrixXu& J_transpose = m_scratchJTranspose; J_transpose= J.transpose(); - static btMatrixXu tmp; + btMatrixXu& tmp = m_scratchTmp; { { @@ -564,7 +563,7 @@ void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal) // add cfm to the diagonal of m_A for ( int i=0; i m_allConstraintPtrArray; btMLCPSolverInterface* m_solver; int m_fallback; - btScalar m_cfm; + + /// The following scratch variables are not stateful -- contents are cleared prior to each use. + /// They are only cached here to avoid extra memory allocations and deallocations and to ensure + /// that multiple instances of the solver can be run in parallel. + btMatrixXu m_scratchJ3; + btMatrixXu m_scratchJInvM3; + btAlignedObjectArray m_scratchOfs; + btMatrixXu m_scratchMInv; + btMatrixXu m_scratchJ; + btMatrixXu m_scratchJTranspose; + btMatrixXu m_scratchTmp; virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); @@ -73,15 +83,6 @@ class btMLCPSolver : public btSequentialImpulseConstraintSolver m_fallback = num; } - btScalar getCfm() const - { - return m_cfm; - } - void setCfm(btScalar cfm) - { - m_cfm = cfm; - } - virtual btConstraintSolverType getSolverType() const { return BT_MLCP_SOLVER; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h index 77cc57c6e0..c0b40ffd9f 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h @@ -23,7 +23,18 @@ subject to the following restrictions: ///This solver is mainly for debug/learning purposes: it is functionally equivalent to the btSequentialImpulseConstraintSolver solver, but much slower (it builds the full LCP matrix) class btSolveProjectedGaussSeidel : public btMLCPSolverInterface { + public: + + btScalar m_leastSquaresResidualThreshold; + btScalar m_leastSquaresResidual; + + btSolveProjectedGaussSeidel() + :m_leastSquaresResidualThreshold(0), + m_leastSquaresResidual(0) + { + } + virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray& limitDependency, int numIterations, bool useSparsity = true) { if (!A.rows()) @@ -36,10 +47,11 @@ class btSolveProjectedGaussSeidel : public btMLCPSolverInterface int i, j, numRows = A.rows(); - float delta; + btScalar delta; for (int k = 0; k =0) { @@ -76,6 +89,17 @@ class btSolveProjectedGaussSeidel : public btMLCPSolverInterface x[i]=lo[i]*s; if (x[i]>hi[i]*s) x[i]=hi[i]*s; + btScalar diff = x[i] - xOld; + m_leastSquaresResidual += diff*diff; + } + + btScalar eps = m_leastSquaresResidualThreshold; + if ((m_leastSquaresResidual < eps) || (k >=(numIterations-1))) + { +#ifdef VERBOSE_PRINTF_RESIDUAL + printf("totalLenSqr = %f at iteration #%d\n", m_leastSquaresResidual,k); +#endif + break; } } return true; diff --git a/Source/ThirdParty/Bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/Source/ThirdParty/Bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h index f59555f94d..82d44c73e0 100644 --- a/Source/ThirdParty/Bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/Source/ThirdParty/Bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -58,8 +58,6 @@ class btRaycastVehicle : public btActionInterface }; private: - btScalar m_tau; - btScalar m_damping; btVehicleRaycaster* m_vehicleRaycaster; btScalar m_pitchControl; btScalar m_steeringValue; diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.cpp b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.cpp index 51f4b33d03..d5de7c1b44 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.cpp +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.cpp @@ -18,6 +18,8 @@ subject to the following restrictions: #include "BulletSoftBody/btSoftBodySolvers.h" #include "btSoftBodyData.h" #include "LinearMath/btSerializer.h" +#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h" +#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h" // @@ -3018,6 +3020,7 @@ void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti) } } + // void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti) { @@ -3029,9 +3032,39 @@ void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti) const sCti& cti = c.m_cti; if (cti.m_colObj->hasContactResponse()) { - btRigidBody* tmpRigid = (btRigidBody*)btRigidBody::upcast(cti.m_colObj); - const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); - const btVector3 vb = c.m_node->m_x-c.m_node->m_q; + btVector3 va(0,0,0); + btRigidBody* rigidCol; + btMultiBodyLinkCollider* multibodyLinkCol; + btScalar* deltaV; + btMultiBodyJacobianData jacobianData; + if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY) + { + rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj); + va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); + } + else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK) + { + multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj); + if (multibodyLinkCol) + { + const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6; + jacobianData.m_jacobians.resize(ndof); + jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof); + btScalar* jac=&jacobianData.m_jacobians[0]; + + multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m); + deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0]; + multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0],deltaV,jacobianData.scratch_r, jacobianData.scratch_v); + + btScalar vel = 0.0; + for (int j = 0; j < ndof ; ++j) { + vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j]; + } + va = cti.m_normal*vel*dt; + } + } + + const btVector3 vb = c.m_node->m_x-c.m_node->m_q; const btVector3 vr = vb-va; const btScalar dn = btDot(vr, cti.m_normal); if(dn<=SIMD_EPSILON) @@ -3041,8 +3074,20 @@ void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti) // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst ); c.m_node->m_x -= impulse * c.m_c2; - if (tmpRigid) - tmpRigid->applyImpulse(impulse,c.m_c1); + + if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY) + { + if (rigidCol) + rigidCol->applyImpulse(impulse,c.m_c1); + } + else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK) + { + if (multibodyLinkCol) + { + double multiplier = 0.5; + multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV,-impulse.length()*multiplier); + } + } } } } diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.h index bd5846bfb6..11ef57bee4 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.h +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBody.h @@ -232,15 +232,18 @@ class btSoftBody : public btCollisionObject int m_battach:1; // Attached }; /* Link */ - struct Link : Feature + ATTRIBUTE_ALIGNED16(struct) Link : Feature { + btVector3 m_c3; // gradient Node* m_n[2]; // Node pointers btScalar m_rl; // Rest length int m_bbending:1; // Bending link btScalar m_c0; // (ima+imb)*kLST btScalar m_c1; // rl^2 btScalar m_c2; // |gradient|^2/c0 - btVector3 m_c3; // gradient + + BT_DECLARE_ALIGNED_ALLOCATOR(); + }; /* Face */ struct Face : Feature diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp index 9f0d44526b..ab84bddf2a 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -120,8 +120,8 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1); //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//?? btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex); - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr); + ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS; + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr); colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->~btCollisionAlgorithm(); @@ -164,7 +164,8 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1); btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//?? - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr); + ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS; + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr); colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->~btCollisionAlgorithm(); diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp index 293a393e55..51fcd16da4 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -123,8 +123,9 @@ static inline T average(const btAlignedObjectArray& items) return(sum(items)/n); } +#if 0 // -static inline btScalar tetravolume(const btVector3& x0, + inline static btScalar tetravolume(const btVector3& x0, const btVector3& x1, const btVector3& x2, const btVector3& x3) @@ -134,6 +135,7 @@ static inline btScalar tetravolume(const btVector3& x0, const btVector3 c=x3-x0; return(btDot(a,btCross(b,c))); } +#endif // #if 0 diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyInternals.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyInternals.h index 759509a1d8..1ad82616ea 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyInternals.h +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftBodyInternals.h @@ -422,7 +422,7 @@ static inline btVector3 BaryCoord( const btVector3& a, } // -static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, +inline static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, const btVector3& a, const btVector3& b, const btScalar accuracy, @@ -451,6 +451,25 @@ static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, return(-1); } +inline static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, + const btVector3& x, + btSoftBody::sMedium& medium) +{ + medium.m_velocity = btVector3(0,0,0); + medium.m_pressure = 0; + medium.m_density = wfi->air_density; + if(wfi->water_density>0) + { + const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset); + if(depth>0) + { + medium.m_density = wfi->water_density; + medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); + } + } +} + + // static inline btVector3 NormalizeAny(const btVector3& v) { @@ -504,23 +523,7 @@ static inline btScalar VolumeOf( const btVector3& x0, } // -static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, - const btVector3& x, - btSoftBody::sMedium& medium) -{ - medium.m_velocity = btVector3(0,0,0); - medium.m_pressure = 0; - medium.m_density = wfi->air_density; - if(wfi->water_density>0) - { - const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset); - if(depth>0) - { - medium.m_density = wfi->water_density; - medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); - } - } -} + // static inline void ApplyClampedForce( btSoftBody::Node& n, diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp new file mode 100644 index 0000000000..4e76dca9db --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp @@ -0,0 +1,367 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without 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. +*/ + + +#include "btSoftMultiBodyDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//softbody & helpers +#include "BulletSoftBody/btSoftBody.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "BulletSoftBody/btDefaultSoftBodySolver.h" +#include "LinearMath/btSerializer.h" + + +btSoftMultiBodyDynamicsWorld::btSoftMultiBodyDynamicsWorld( + btDispatcher* dispatcher, + btBroadphaseInterface* pairCache, + btMultiBodyConstraintSolver* constraintSolver, + btCollisionConfiguration* collisionConfiguration, + btSoftBodySolver *softBodySolver ) : + btMultiBodyDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration), + m_softBodySolver( softBodySolver ), + m_ownsSolver(false) +{ + if( !m_softBodySolver ) + { + void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16); + m_softBodySolver = new(ptr) btDefaultSoftBodySolver(); + m_ownsSolver = true; + } + + m_drawFlags = fDrawFlags::Std; + m_drawNodeTree = true; + m_drawFaceTree = false; + m_drawClusterTree = false; + m_sbi.m_broadphase = pairCache; + m_sbi.m_dispatcher = dispatcher; + m_sbi.m_sparsesdf.Initialize(); + m_sbi.m_sparsesdf.Reset(); + + m_sbi.air_density = (btScalar)1.2; + m_sbi.water_density = 0; + m_sbi.water_offset = 0; + m_sbi.water_normal = btVector3(0,0,0); + m_sbi.m_gravity.setValue(0,-10,0); + + m_sbi.m_sparsesdf.Initialize(); + + +} + +btSoftMultiBodyDynamicsWorld::~btSoftMultiBodyDynamicsWorld() +{ + if (m_ownsSolver) + { + m_softBodySolver->~btSoftBodySolver(); + btAlignedFree(m_softBodySolver); + } +} + +void btSoftMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep ); + { + BT_PROFILE("predictUnconstraintMotionSoftBody"); + m_softBodySolver->predictMotion( float(timeStep) ); + } +} + +void btSoftMultiBodyDynamicsWorld::internalSingleStepSimulation( btScalar timeStep ) +{ + + // Let the solver grab the soft bodies and if necessary optimize for it + m_softBodySolver->optimize( getSoftBodyArray() ); + + if( !m_softBodySolver->checkInitialized() ) + { + btAssert( "Solver initialization failed\n" ); + } + + btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); + + ///solve soft bodies constraints + solveSoftBodiesConstraints( timeStep ); + + //self collisions + for ( int i=0;idefaultCollisionHandler(psb); + } + + ///update soft bodies + m_softBodySolver->updateSoftBodies( ); + + // End solver-wise simulation step + // /////////////////////////////// + +} + +void btSoftMultiBodyDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep ) +{ + BT_PROFILE("solveSoftConstraints"); + + if(m_softBodies.size()) + { + btSoftBody::solveClusters(m_softBodies); + } + + // Solve constraints solver-wise + m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() ); + +} + +void btSoftMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask) +{ + m_softBodies.push_back(body); + + // Set the soft body solver that will deal with this body + // to be the world's solver + body->setSoftBodySolver( m_softBodySolver ); + + btCollisionWorld::addCollisionObject(body, + collisionFilterGroup, + collisionFilterMask); + +} + +void btSoftMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body) +{ + m_softBodies.remove(body); + + btCollisionWorld::removeCollisionObject(body); +} + +void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btSoftBody* body = btSoftBody::upcast(collisionObject); + if (body) + removeSoftBody(body); + else + btDiscreteDynamicsWorld::removeCollisionObject(collisionObject); +} + +void btSoftMultiBodyDynamicsWorld::debugDrawWorld() +{ + btDiscreteDynamicsWorld::debugDrawWorld(); + + if (getDebugDrawer()) + { + int i; + for ( i=0;im_softBodies.size();i++) + { + btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); + btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); + } + + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); + if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); + if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); + } + } + } +} + + + + +struct btSoftSingleRayCallback : public btBroadphaseRayCallback +{ + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; + + const btSoftMultiBodyDynamicsWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; + + btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftMultiBodyDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_world(world), + m_resultCallback(resultCallback) + { + m_rayFromTrans.setIdentity(); + m_rayFromTrans.setOrigin(m_rayFromWorld); + m_rayToTrans.setIdentity(); + m_rayToTrans.setOrigin(m_rayToWorld); + + btVector3 rayDir = (rayToWorld-rayFromWorld); + + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); + + } + + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btSoftMultiBodyDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;igetNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + +} + + +void btSoftMultiBodyDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback) +{ + if (collisionShape->isSoftBody()) { + btSoftBody* softBody = btSoftBody::upcast(collisionObject); + if (softBody) { + btSoftBody::sRayCast softResult; + if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) + { + + if (softResult.fraction<= resultCallback.m_closestHitFraction) + { + + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = 0; + shapeInfo.m_triangleIndex = softResult.index; + // get the normal + btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); + btVector3 normal=-rayDir; + normal.normalize(); + + if (softResult.feature == btSoftBody::eFeature::Face) + { + normal = softBody->m_faces[softResult.index].m_normal; + if (normal.dot(rayDir) > 0) { + // normal always point toward origin of the ray + normal = -normal; + } + } + + btCollisionWorld::LocalRayResult rayResult + (collisionObject, + &shapeInfo, + normal, + softResult.fraction); + bool normalInWorldSpace = true; + resultCallback.addSingleResult(rayResult,normalInWorldSpace); + } + } + } + } + else { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback); + } +} + + +void btSoftMultiBodyDynamicsWorld::serializeSoftBodies(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() & btCollisionObject::CO_SOFT_BODY) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj); + } + } + +} + +void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeDynamicsWorldInfo( serializer); + + serializeSoftBodies(serializer); + + serializeRigidBodies(serializer); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + + diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h new file mode 100644 index 0000000000..7e3ab329f0 --- /dev/null +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h @@ -0,0 +1,108 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without 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 BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H +#define BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h" +#include "BulletSoftBody/btSoftBody.h" + +typedef btAlignedObjectArray btSoftBodyArray; + +class btSoftBodySolver; + +class btSoftMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld +{ + + btSoftBodyArray m_softBodies; + int m_drawFlags; + bool m_drawNodeTree; + bool m_drawFaceTree; + bool m_drawClusterTree; + btSoftBodyWorldInfo m_sbi; + ///Solver classes that encapsulate multiple soft bodies for solving + btSoftBodySolver *m_softBodySolver; + bool m_ownsSolver; + +protected: + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void solveSoftBodiesConstraints( btScalar timeStep ); + + void serializeSoftBodies(btSerializer* serializer); + +public: + + btSoftMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 ); + + virtual ~btSoftMultiBodyDynamicsWorld(); + + virtual void debugDrawWorld(); + + void addSoftBody(btSoftBody* body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter); + + void removeSoftBody(btSoftBody* body); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + int getDrawFlags() const { return(m_drawFlags); } + void setDrawFlags(int f) { m_drawFlags=f; } + + btSoftBodyWorldInfo& getWorldInfo() + { + return m_sbi; + } + const btSoftBodyWorldInfo& getWorldInfo() const + { + return m_sbi; + } + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SOFT_MULTIBODY_DYNAMICS_WORLD; + } + + btSoftBodyArray& getSoftBodyArray() + { + return m_softBodies; + } + + const btSoftBodyArray& getSoftBodyArray() const + { + return m_softBodies; + } + + + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback); + + virtual void serialize(btSerializer* serializer); + +}; + +#endif //BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h index a9b513e363..93fcc6065b 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -31,8 +31,8 @@ class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm // bool m_ownManifold; // btPersistentManifold* m_manifoldPtr; - btSoftBody* m_softBody; - btCollisionObject* m_rigidCollisionObject; + //btSoftBody* m_softBody; + //btCollisionObject* m_rigidCollisionObject; ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean bool m_isSwapped; diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp index 653d5a06b4..204b4f576d 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -125,7 +125,7 @@ void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep ) } -void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask) +void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask) { m_softBodies.push_back(body); diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h index 3e0efafd6c..d921a6488d 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -54,7 +54,7 @@ class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld virtual void debugDrawWorld(); - void addSoftBody(btSoftBody* body,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + void addSoftBody(btSoftBody* body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter); void removeSoftBody(btSoftBody* body); diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h index 43b1439cc5..4eab7aea2f 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -30,8 +30,8 @@ class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm bool m_ownManifold; btPersistentManifold* m_manifoldPtr; - btSoftBody* m_softBody0; - btSoftBody* m_softBody1; +// btSoftBody* m_softBody0; +// btSoftBody* m_softBody1; public: diff --git a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSparseSDF.h b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSparseSDF.h index bcf0c79825..ba437c28ef 100644 --- a/Source/ThirdParty/Bullet/src/BulletSoftBody/btSparseSDF.h +++ b/Source/ThirdParty/Bullet/src/BulletSoftBody/btSparseSDF.h @@ -185,7 +185,7 @@ struct btSparseSdf { ++nprobes; ++ncells; - int sz = sizeof(Cell); + //int sz = sizeof(Cell); if (ncells>m_clampCells) { static int numResets=0; diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btAlignedAllocator.cpp b/Source/ThirdParty/Bullet/src/LinearMath/btAlignedAllocator.cpp index a65296c6ab..e5f6040c43 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btAlignedAllocator.cpp +++ b/Source/ThirdParty/Bullet/src/LinearMath/btAlignedAllocator.cpp @@ -105,30 +105,94 @@ void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) } #ifdef BT_DEBUG_MEMORY_ALLOCATIONS + +static int allocations_id[10241024]; +static int allocations_bytes[10241024]; +static int mynumallocs = 0; +#include + +int btDumpMemoryLeaks() +{ + int totalLeak = 0; + + for (int i=0;i +struct btDebugPtrMagic +{ + union + { + void** vptrptr; + void* vptr; + int* iptr; + char* cptr; + }; +}; + + void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) { + if (size==0) + { + printf("Whaat? size==0"); + return 0; + } + static int allocId = 0; + void *ret; char *real; +// to find some particular memory leak, you could do something like this: +// if (allocId==172) +// { +// printf("catch me!\n"); +// } +// if (size>1024*1024) +// { +// printf("big alloc!%d\n", size); +// } + gTotalBytesAlignedAllocs += size; gNumAlignedAllocs++; - real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); +int sz4prt = 4*sizeof(void *); + + real = (char *)sAllocFunc(size + sz4prt + (alignment-1)); if (real) { - ret = (void*) btAlignPointer(real + 2*sizeof(void *), alignment); - *((void **)(ret)-1) = (void *)(real); - *((int*)(ret)-2) = size; + + ret = (void*) btAlignPointer(real + sz4prt, alignment); + btDebugPtrMagic p; + p.vptr = ret; + p.cptr-=sizeof(void*); + *p.vptrptr = (void*)real; + p.cptr-=sizeof(void*); + *p.iptr = size; + p.cptr-=sizeof(void*); + *p.iptr = allocId; + + allocations_id[mynumallocs] = allocId; + allocations_bytes[mynumallocs] = size; + mynumallocs++; } else { ret = (void *)(real);//?? } - printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); - + printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n",allocId,real, filename,line,size,gTotalBytesAlignedAllocs); + allocId++; + int* ptr = (int*)ret; *ptr = 12; return (ret); @@ -138,19 +202,43 @@ void btAlignedFreeInternal (void* ptr,int line,char* filename) { void* real; - gNumAlignedFree++; if (ptr) { - real = *((void **)(ptr)-1); - int size = *((int*)(ptr)-2); - gTotalBytesAlignedAllocs -= size; - - printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); + gNumAlignedFree++; + + btDebugPtrMagic p; + p.vptr = ptr; + p.cptr-=sizeof(void*); + real = *p.vptrptr; + p.cptr-=sizeof(void*); + int size = *p.iptr; + p.cptr-=sizeof(void*); + int allocId = *p.iptr; + + bool found = false; + + for (int i=0;i //for placement new #endif //BT_USE_PLACEMENT_NEW +// The register keyword is deprecated in C++11 so don't use it. +#if __cplusplus > 199711L +#define BT_REGISTER +#else +#define BT_REGISTER register +#endif ///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods ///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data @@ -211,7 +217,7 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T()) { - const register int curSize = size(); + const BT_REGISTER int curSize = size(); if (newsize < curSize) { @@ -238,7 +244,7 @@ class btAlignedObjectArray } SIMD_FORCE_INLINE T& expandNonInitializing( ) { - const register int sz = size(); + const BT_REGISTER int sz = size(); if( sz == capacity() ) { reserve( allocSize(size()) ); @@ -251,7 +257,7 @@ class btAlignedObjectArray SIMD_FORCE_INLINE T& expand( const T& fillValue=T()) { - const register int sz = size(); + const BT_REGISTER int sz = size(); if( sz == capacity() ) { reserve( allocSize(size()) ); @@ -267,7 +273,7 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void push_back(const T& _Val) { - const register int sz = size(); + const BT_REGISTER int sz = size(); if( sz == capacity() ) { reserve( allocSize(size()) ); @@ -316,7 +322,7 @@ class btAlignedObjectArray { public: - bool operator() ( const T& a, const T& b ) + bool operator() ( const T& a, const T& b ) const { return ( a < b ); } @@ -470,15 +476,18 @@ class btAlignedObjectArray return index; } + void removeAtIndex(int index) + { + if (index //#define BT_DEBUG_OSTREAM diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.cpp b/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.cpp index a4dca7fdd4..b3664faa4e 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.cpp +++ b/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.cpp @@ -30,8 +30,7 @@ namespace } } -const btScalar btPolarDecomposition::DEFAULT_TOLERANCE = btScalar(0.0001); -const unsigned int btPolarDecomposition::DEFAULT_MAX_ITERATIONS = 16; + btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations) : m_tolerance(tolerance) diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.h b/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.h index 5615667641..1feea0f78e 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btPolarDecomposition.h @@ -14,8 +14,7 @@ class btPolarDecomposition { public: - static const btScalar DEFAULT_TOLERANCE; - static const unsigned int DEFAULT_MAX_ITERATIONS; + /** * Creates an instance with optional parameters. @@ -25,8 +24,8 @@ class btPolarDecomposition * @param maxIterations - the maximum number of iterations used to achieve * convergence */ - btPolarDecomposition(btScalar tolerance = DEFAULT_TOLERANCE, - unsigned int maxIterations = DEFAULT_MAX_ITERATIONS); + btPolarDecomposition(btScalar tolerance = btScalar(0.0001), + unsigned int maxIterations = 16); /** * Decomposes a matrix into orthogonal and symmetric, positive-definite diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btPoolAllocator.h b/Source/ThirdParty/Bullet/src/LinearMath/btPoolAllocator.h index ef2084537a..efdeda8ffc 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btPoolAllocator.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btPoolAllocator.h @@ -18,6 +18,7 @@ subject to the following restrictions: #include "btScalar.h" #include "btAlignedAllocator.h" +#include "btThreads.h" ///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. class btPoolAllocator @@ -27,6 +28,7 @@ class btPoolAllocator int m_freeCount; void* m_firstFree; unsigned char* m_pool; + btSpinMutex m_mutex; // only used if BT_THREADSAFE public: @@ -71,11 +73,16 @@ class btPoolAllocator { // release mode fix (void)size; + btMutexLock(&m_mutex); btAssert(!size || size<=m_elemSize); - btAssert(m_freeCount>0); + //btAssert(m_freeCount>0); // should return null if all full void* result = m_firstFree; - m_firstFree = *(void**)m_firstFree; - --m_freeCount; + if (NULL != m_firstFree) + { + m_firstFree = *(void**)m_firstFree; + --m_freeCount; + } + btMutexUnlock(&m_mutex); return result; } @@ -95,9 +102,11 @@ class btPoolAllocator if (ptr) { btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); + btMutexLock(&m_mutex); *(void**)ptr = m_firstFree; m_firstFree = ptr; ++m_freeCount; + btMutexUnlock(&m_mutex); } } diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btQuaternion.h b/Source/ThirdParty/Bullet/src/LinearMath/btQuaternion.h index ede7693840..32f0f85d26 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btQuaternion.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btQuaternion.h @@ -418,22 +418,21 @@ class btQuaternion : public btQuadWord { return btAcos(dot(q) / s) * btScalar(2.0); } - /**@brief Return the angle of rotation represented by this quaternion */ + /**@brief Return the angle [0, 2Pi] of rotation represented by this quaternion */ btScalar getAngle() const { btScalar s = btScalar(2.) * btAcos(m_floats[3]); return s; } - /**@brief Return the angle of rotation represented by this quaternion along the shortest path*/ + /**@brief Return the angle [0, Pi] of rotation represented by this quaternion along the shortest path */ btScalar getAngleShortestPath() const { btScalar s; - if (dot(*this) < 0) + if (m_floats[3] >= 0) s = btScalar(2.) * btAcos(m_floats[3]); else s = btScalar(2.) * btAcos(-m_floats[3]); - return s; } @@ -533,25 +532,29 @@ class btQuaternion : public btQuadWord { * Slerp interpolates assuming constant velocity. */ btQuaternion slerp(const btQuaternion& q, const btScalar& t) const { - btScalar magnitude = btSqrt(length2() * q.length2()); - btAssert(magnitude > btScalar(0)); - btScalar product = dot(q) / magnitude; - if (btFabs(product) < btScalar(1)) + const btScalar magnitude = btSqrt(length2() * q.length2()); + btAssert(magnitude > btScalar(0)); + + const btScalar product = dot(q) / magnitude; + const btScalar absproduct = btFabs(product); + + if(absproduct < btScalar(1.0 - SIMD_EPSILON)) { - // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp - const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1); - - const btScalar theta = btAcos(sign * product); - const btScalar s1 = btSin(sign * t * theta); - const btScalar d = btScalar(1.0) / btSin(theta); - const btScalar s0 = btSin((btScalar(1.0) - t) * theta); - - return btQuaternion( - (m_floats[0] * s0 + q.x() * s1) * d, - (m_floats[1] * s0 + q.y() * s1) * d, - (m_floats[2] * s0 + q.z() * s1) * d, - (m_floats[3] * s0 + q.m_floats[3] * s1) * d); + // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp + const btScalar theta = btAcos(absproduct); + const btScalar d = btSin(theta); + btAssert(d > btScalar(0)); + + const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1); + const btScalar s0 = btSin((btScalar(1.0) - t) * theta) / d; + const btScalar s1 = btSin(sign * t * theta) / d; + + return btQuaternion( + (m_floats[0] * s0 + q.x() * s1), + (m_floats[1] * s0 + q.y() * s1), + (m_floats[2] * s0 + q.z() * s1), + (m_floats[3] * s0 + q.w() * s1)); } else { diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.cpp b/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.cpp index d88d965a4c..16ca88cdc0 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.cpp +++ b/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.cpp @@ -15,10 +15,8 @@ #include "btQuickprof.h" -#ifndef BT_NO_PROFILE -static btClock gProfileClock; #ifdef __CELLOS_LV2__ @@ -30,6 +28,10 @@ static btClock gProfileClock; #if defined (SUNOS) || defined (__SUNOS__) #include #endif +#ifdef __APPLE__ +#include +#include +#endif #if defined(WIN32) || defined(_WIN32) @@ -55,6 +57,12 @@ static btClock gProfileClock; #else //_WIN32 #include + +#ifdef BT_LINUX_REALTIME +//required linking against rt (librt) +#include +#endif //BT_LINUX_REALTIME + #endif //_WIN32 #define mymin(a,b) (a > b ? a : b) @@ -65,12 +73,14 @@ struct btClockData #ifdef BT_USE_WINDOWS_TIMERS LARGE_INTEGER mClockFrequency; LONGLONG mStartTick; - LONGLONG mPrevElapsedTime; LARGE_INTEGER mStartTime; #else #ifdef __CELLOS_LV2__ uint64_t mStartTime; #else +#ifdef __APPLE__ + uint64_t mStartTimeNano; +#endif struct timeval mStartTime; #endif #endif //__CELLOS_LV2__ @@ -111,7 +121,6 @@ void btClock::reset() #ifdef BT_USE_WINDOWS_TIMERS QueryPerformanceCounter(&m_data->mStartTime); m_data->mStartTick = GetTickCount64(); - m_data->mPrevElapsedTime = 0; #else #ifdef __CELLOS_LV2__ @@ -121,6 +130,9 @@ void btClock::reset() SYS_TIMEBASE_GET( newTime ); m_data->mStartTime = newTime; #else +#ifdef __APPLE__ + m_data->mStartTimeNano = mach_absolute_time(); +#endif gettimeofday(&m_data->mStartTime, 0); #endif #endif @@ -128,7 +140,7 @@ void btClock::reset() /// Returns the time in ms since the last call to reset or since /// the btClock was created. -unsigned long int btClock::getTimeMilliseconds() +unsigned long long int btClock::getTimeMilliseconds() { #ifdef BT_USE_WINDOWS_TIMERS LARGE_INTEGER currentTime; @@ -138,27 +150,6 @@ unsigned long int btClock::getTimeMilliseconds() // Compute the number of millisecond ticks elapsed. unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / m_data->mClockFrequency.QuadPart); - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = (unsigned long)(GetTickCount64() - m_data->mStartTick); - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - m_data->mClockFrequency.QuadPart / 1000, elapsedTime - - m_data->mPrevElapsedTime); - m_data->mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - - // Recompute the number of millisecond ticks elapsed. - msecTicks = (unsigned long)(1000 * elapsedTime / - m_data->mClockFrequency.QuadPart); - } - - // Store the current elapsed time for adjustments next time. - m_data->mPrevElapsedTime = elapsedTime; return msecTicks; #else @@ -184,41 +175,19 @@ unsigned long int btClock::getTimeMilliseconds() /// Returns the time in us since the last call to reset or since /// the Clock was created. -unsigned long int btClock::getTimeMicroseconds() +unsigned long long int btClock::getTimeMicroseconds() { #ifdef BT_USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; + //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx + LARGE_INTEGER currentTime, elapsedTime; + QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - + elapsedTime.QuadPart = currentTime.QuadPart - m_data->mStartTime.QuadPart; + elapsedTime.QuadPart *= 1000000; + elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart; - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - m_data->mClockFrequency.QuadPart); - - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = (unsigned long)(GetTickCount64() - m_data->mStartTick); - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - m_data->mClockFrequency.QuadPart / 1000, elapsedTime - - m_data->mPrevElapsedTime); - m_data->mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - } - - // Store the current elapsed time for adjustments next time. - m_data->mPrevElapsedTime = elapsedTime; - - // Convert to microseconds. - unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / - m_data->mClockFrequency.QuadPart); - - return usecTicks; + return (unsigned long long) elapsedTime.QuadPart; #else #ifdef __CELLOS_LV2__ @@ -240,6 +209,66 @@ unsigned long int btClock::getTimeMicroseconds() #endif } +unsigned long long int btClock::getTimeNanoseconds() +{ +#ifdef BT_USE_WINDOWS_TIMERS + //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx + LARGE_INTEGER currentTime, elapsedTime; + + QueryPerformanceCounter(¤tTime); + elapsedTime.QuadPart = currentTime.QuadPart - + m_data->mStartTime.QuadPart; + elapsedTime.QuadPart *= 1e9; + elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart; + + return (unsigned long long) elapsedTime.QuadPart; +#else + +#ifdef __CELLOS_LV2__ + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1e9; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + + return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); +#else +#ifdef __APPLE__ + uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano; + static long double conversion = 0.0L; + if( 0.0L == conversion ) + { + // attempt to get conversion to nanoseconds + mach_timebase_info_data_t info; + int err = mach_timebase_info( &info ); + if( err ) + { + btAssert(0); + conversion = 1.; + } + conversion = info.numer / info.denom; + } + return (ticks * conversion); + + +#else//__APPLE__ + +#ifdef BT_LINUX_REALTIME + timespec ts; + clock_gettime(CLOCK_REALTIME,&ts); + return 1000000000*ts.tv_sec + ts.tv_nsec; +#else + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 + + (currentTime.tv_usec - m_data->mStartTime.tv_usec)*1000; +#endif //BT_LINUX_REALTIME + +#endif//__APPLE__ +#endif//__CELLOS_LV2__ +#endif +} /// Returns the time in s since the last call to reset or since @@ -250,6 +279,10 @@ btScalar btClock::getTimeSeconds() return btScalar(getTimeMicroseconds()) * microseconds_to_seconds; } +#ifndef BT_NO_PROFILE + + +static btClock gProfileClock; inline void Profile_Get_Ticks(unsigned long int * ticks) @@ -265,7 +298,6 @@ inline float Profile_Get_Tick_Rate(void) } - /*************************************************************************************************** ** ** CProfileNode @@ -367,6 +399,7 @@ bool CProfileNode::Return( void ) if ( --RecursionCounter == 0 && TotalCalls != 0 ) { unsigned long int time; Profile_Get_Ticks(&time); + time-=StartTime; TotalTime += (float)time / Profile_Get_Tick_Rate(); } @@ -434,11 +467,71 @@ void CProfileIterator::Enter_Parent( void ) ** ***************************************************************************************************/ -CProfileNode CProfileManager::Root( "Root", NULL ); -CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; + + + +CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT]={ + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), + CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL) +}; + + +CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT]= +{ + &gRoots[ 0], &gRoots[ 1], &gRoots[ 2], &gRoots[ 3], + &gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7], + &gRoots[ 8], &gRoots[ 9], &gRoots[10], &gRoots[11], + &gRoots[12], &gRoots[13], &gRoots[14], &gRoots[15], + &gRoots[16], &gRoots[17], &gRoots[18], &gRoots[19], + &gRoots[20], &gRoots[21], &gRoots[22], &gRoots[23], + &gRoots[24], &gRoots[25], &gRoots[26], &gRoots[27], + &gRoots[28], &gRoots[29], &gRoots[30], &gRoots[31], + &gRoots[32], &gRoots[33], &gRoots[34], &gRoots[35], + &gRoots[36], &gRoots[37], &gRoots[38], &gRoots[39], + &gRoots[40], &gRoots[41], &gRoots[42], &gRoots[43], + &gRoots[44], &gRoots[45], &gRoots[46], &gRoots[47], + &gRoots[48], &gRoots[49], &gRoots[50], &gRoots[51], + &gRoots[52], &gRoots[53], &gRoots[54], &gRoots[55], + &gRoots[56], &gRoots[57], &gRoots[58], &gRoots[59], + &gRoots[60], &gRoots[61], &gRoots[62], &gRoots[63], +}; + + int CProfileManager::FrameCounter = 0; unsigned long int CProfileManager::ResetTime = 0; +CProfileIterator * CProfileManager::Get_Iterator( void ) +{ + + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return 0; + + return new CProfileIterator( &gRoots[threadIndex]); +} + +void CProfileManager::CleanupMemory(void) +{ + for (int i=0;iGet_Name()) { - CurrentNode = CurrentNode->Get_Sub_Node( name ); + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return; + + if (name != gCurrentNodes[threadIndex]->Get_Name()) { + gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node( name ); } - CurrentNode->Call(); + gCurrentNodes[threadIndex]->Call(); } @@ -468,14 +565,22 @@ void CProfileManager::Start_Profile( const char * name ) *=============================================================================================*/ void CProfileManager::Stop_Profile( void ) { + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return; + // Return will indicate whether we should back up to our parent (we may // be profiling a recursive function) - if (CurrentNode->Return()) { - CurrentNode = CurrentNode->Get_Parent(); + if (gCurrentNodes[threadIndex]->Return()) { + gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Parent(); } } + + + + /*********************************************************************************************** * CProfileManager::Reset -- Reset the contents of the profiling system * * * @@ -484,8 +589,11 @@ void CProfileManager::Stop_Profile( void ) void CProfileManager::Reset( void ) { gProfileClock.reset(); - Root.Reset(); - Root.Call(); + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return; + gRoots[threadIndex].Reset(); + gRoots[threadIndex].Call(); FrameCounter = 0; Profile_Get_Ticks(&ResetTime); } @@ -575,4 +683,99 @@ void CProfileManager::dumpAll() +unsigned int btQuickprofGetCurrentThreadIndex2() +{ + const unsigned int kNullIndex = ~0U; +#ifdef _WIN32 + __declspec( thread ) static unsigned int sThreadIndex = kNullIndex; +#else +#ifdef __APPLE__ + #if TARGET_OS_IPHONE + unsigned int sThreadIndex = 0; + return -1; + #else + static __thread unsigned int sThreadIndex = kNullIndex; + #endif +#else//__APPLE__ +#if __linux__ + static __thread unsigned int sThreadIndex = kNullIndex; +#else + unsigned int sThreadIndex = 0; + return -1; +#endif +#endif//__APPLE__ + +#endif + static int gThreadCounter=0; + + if ( sThreadIndex == kNullIndex ) + { + sThreadIndex = gThreadCounter++; + } + return sThreadIndex; +} + +void btEnterProfileZoneDefault(const char* name) +{ + CProfileManager::Start_Profile( name ); +} +void btLeaveProfileZoneDefault() +{ + CProfileManager::Stop_Profile(); +} + + +#else +void btEnterProfileZoneDefault(const char* name) +{ +} +void btLeaveProfileZoneDefault() +{ +} #endif //BT_NO_PROFILE + + + + + +static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault; +static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault; + +void btEnterProfileZone(const char* name) +{ + (bts_enterFunc)(name); +} +void btLeaveProfileZone() +{ + (bts_leaveFunc)(); +} + +btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc() +{ + return bts_enterFunc ; +} +btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc() +{ + return bts_leaveFunc; +} + + +void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc) +{ + bts_enterFunc = enterFunc; +} +void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc) +{ + bts_leaveFunc = leaveFunc; +} + +CProfileSample::CProfileSample( const char * name ) +{ + btEnterProfileZone(name); +} + +CProfileSample::~CProfileSample( void ) +{ + btLeaveProfileZone(); +} + diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.h b/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.h index b6b2465e99..b3e3265bb5 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btQuickprof.h @@ -10,24 +10,13 @@ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). +// Modified by Lasse Oorni for Urho3D #ifndef BT_QUICK_PROF_H #define BT_QUICK_PROF_H -//To disable built-in profiling, please comment out next line -// Urho3D: disable profiling, as Urho has its own hierarchic profiler -#define BT_NO_PROFILE 1 -#ifndef BT_NO_PROFILE -#include //@todo remove this, backwards compatibility #include "btScalar.h" -#include "btAlignedAllocator.h" -#include - - - - - #define USE_BT_CLOCK 1 #ifdef USE_BT_CLOCK @@ -48,12 +37,14 @@ class btClock /// Returns the time in ms since the last call to reset or since /// the btClock was created. - unsigned long int getTimeMilliseconds(); + unsigned long long int getTimeMilliseconds(); /// Returns the time in us since the last call to reset or since /// the Clock was created. - unsigned long int getTimeMicroseconds(); + unsigned long long int getTimeMicroseconds(); + unsigned long long int getTimeNanoseconds(); + /// Returns the time in s since the last call to reset or since /// the Clock was created. btScalar getTimeSeconds(); @@ -64,6 +55,37 @@ class btClock #endif //USE_BT_CLOCK +typedef void (btEnterProfileZoneFunc)(const char* msg); +typedef void (btLeaveProfileZoneFunc)(); + +btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc(); +btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc(); + + + +void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc); +void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc); + + +//To disable built-in profiling, please comment out next line +// Urho3D: built-in profiling disabled, since Urho3D has its own hierarchic profiler +#define BT_NO_PROFILE 1 +#ifndef BT_NO_PROFILE +//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined, +//otherwise returns thread index in range [0..maxThreads] +unsigned int btQuickprofGetCurrentThreadIndex2(); +const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64; + +#include //@todo remove this, backwards compatibility + +#include "btAlignedAllocator.h" +#include + + + + + + @@ -149,21 +171,21 @@ class CProfileManager { static void Start_Profile( const char * name ); static void Stop_Profile( void ); - static void CleanupMemory(void) - { - Root.CleanupMemory(); - } + static void CleanupMemory(void); +// { +// Root.CleanupMemory(); +// } static void Reset( void ); static void Increment_Frame_Counter( void ); static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } static float Get_Time_Since_Reset( void ); - static CProfileIterator * Get_Iterator( void ) - { - - return new CProfileIterator( &Root ); - } + static CProfileIterator * Get_Iterator( void ); +// { +// +// return new CProfileIterator( &Root ); +// } static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } static void dumpRecursive(CProfileIterator* profileIterator, int spacing); @@ -171,37 +193,27 @@ class CProfileManager { static void dumpAll(); private: - static CProfileNode Root; - static CProfileNode * CurrentNode; + static int FrameCounter; static unsigned long int ResetTime; }; + + +#endif //#ifndef BT_NO_PROFILE + ///ProfileSampleClass is a simple way to profile a function's scope ///Use the BT_PROFILE macro at the start of scope to time class CProfileSample { public: - CProfileSample( const char * name ) - { - CProfileManager::Start_Profile( name ); - } - - ~CProfileSample( void ) - { - CProfileManager::Stop_Profile(); - } -}; + CProfileSample( const char * name ); + ~CProfileSample( void ); +}; #define BT_PROFILE( name ) CProfileSample __profile( name ) -#else - -#define BT_PROFILE( name ) - -#endif //#ifndef BT_NO_PROFILE - #endif //BT_QUICK_PROF_H diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btScalar.h b/Source/ThirdParty/Bullet/src/LinearMath/btScalar.h index 99746614e9..60b2efa1a9 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btScalar.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btScalar.h @@ -18,6 +18,7 @@ subject to the following restrictions: #ifndef BT_SCALAR_H #define BT_SCALAR_H + #ifdef BT_MANAGED_CODE //Aligned data types not supported in managed code #pragma unmanaged @@ -29,7 +30,7 @@ subject to the following restrictions: #include /* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ -#define BT_BULLET_VERSION 284 +#define BT_BULLET_VERSION 286 inline int btGetVersion() { @@ -44,7 +45,7 @@ inline int btGetVersion() // Urho3D - enable BT_USE_SSE for MinGW #if defined(_WIN32) && !defined(__MINGW32__) - #if defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a @@ -59,7 +60,7 @@ inline int btGetVersion() //#define BT_HAS_ALIGNED_ALLOCATOR #pragma warning(disable : 4324) // disable padding warning // #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. -// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines + #pragma warning(disable:4996) //Turn off warnings about deprecated C routines // #pragma warning(disable:4786) // Disable the "debug name too long" warning #define SIMD_FORCE_INLINE __forceinline @@ -108,7 +109,7 @@ inline int btGetVersion() #ifdef BT_DEBUG #ifdef _MSC_VER #include - #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }} + #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }} #else//_MSC_VER #include #define btAssert assert @@ -183,6 +184,7 @@ inline int btGetVersion() #define BT_USE_SIMD_VECTOR3 #define BT_USE_SSE //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries + //if apps run into issues, we will disable the next line #define BT_USE_SSE_IN_API #ifdef BT_USE_SSE // include appropriate SSE level @@ -197,12 +199,14 @@ inline int btGetVersion() #endif #endif //BT_USE_SSE #elif defined( __ARM_NEON__ ) + #ifdef __clang__ #define BT_USE_NEON 1 #define BT_USE_SIMD_VECTOR3 - #ifdef BT_USE_NEON + #if defined BT_USE_NEON && defined (__clang__) #include #endif//BT_USE_NEON + #endif //__clang__ #endif//__arm__ #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline)) @@ -261,7 +265,7 @@ inline int btGetVersion() #define btFullAssert(x) #define btLikely(_c) _c #define btUnlikely(_c) _c -#endif +#endif //__APPLE__ #endif // LIBSPE2 diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.cpp b/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.cpp index 8fdcfb1421..2b5740b40f 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.cpp +++ b/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.cpp @@ -1,5 +1,5 @@ char sBulletDNAstr[]= { -char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(123),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109), +char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-128),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109), char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95), char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111), char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110), @@ -90,505 +90,511 @@ char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),c char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84), char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116), char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109), -char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114), -char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99), -char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114), -char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84), -char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116), -char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108), -char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84), -char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95), -char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105), -char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67), -char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73), -char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108), -char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110), -char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0), -char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97), -char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103), -char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70), -char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101), -char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105), -char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0), -char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101), -char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112), -char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103), -char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103), -char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76), -char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), -char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103), -char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100), -char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117), -char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111), -char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103), -char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110), -char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116), -char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65), -char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101), -char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112), -char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100), -char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97), -char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68), -char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108), -char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100), -char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109), -char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98), -char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104), -char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100), -char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97), -char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109), -char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101), -char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102), -char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), -char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108), -char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101), -char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114), -char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), -char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105), -char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116), -char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111), -char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119), -char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110), -char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(100),char(97),char(109),char(112), -char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109), -char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), -char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105), -char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), -char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110), -char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116), -char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109), -char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110), -char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105), -char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83), -char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103), -char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66), -char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82), -char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95), -char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110), -char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114), -char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110), -char(101),char(97),char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115), -char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105), -char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105), -char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98), -char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83), -char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97), -char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115), -char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83), -char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91), -char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109), -char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110), -char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), -char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114), -char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97), -char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), -char(97),char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110), -char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97), -char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115), -char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109), -char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105), -char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114), -char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103), -char(117),char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95), -char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91), -char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116), -char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95), -char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103), -char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79), -char(114),char(100),char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105), -char(115),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109), -char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114), -char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114), -char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109), -char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116), -char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112), -char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95), -char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97), -char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114), -char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108), -char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110), -char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97), -char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109), -char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105), -char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105), -char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101), -char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(105), -char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117), -char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109), -char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105), -char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118), -char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99), -char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114), -char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109), -char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101), -char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95), -char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99), -char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99), -char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52), -char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0), -char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97), -char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111), -char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0), -char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109), -char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118), -char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116), -char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105), -char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109), -char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110), -char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114), -char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101), -char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101), -char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101), -char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109), -char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100), -char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115), -char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111), -char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117), -char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67), -char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109), -char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97), -char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105), -char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116), -char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111), -char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111), -char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97), -char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110), -char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111), -char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0), -char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109), -char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0), -char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91), -char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95), -char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115), -char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109), -char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115), -char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115), -char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115), -char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109), -char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95), -char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0), -char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102), -char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115), -char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70), -char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104), -char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116), -char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95), -char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102), -char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109), -char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111), -char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0), -char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0), -char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100), -char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115), -char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110), -char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109), -char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97), -char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70), -char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97), -char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67), -char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0), -char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97), -char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67), -char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95), -char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102), -char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91), -char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109), -char(91),char(54),char(93),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106), -char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108), -char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109), -char(95),char(108),char(105),char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110), -char(100),char(101),char(120),char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115), -char(86),char(97),char(114),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91), -char(55),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106), -char(111),char(105),char(110),char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(42),char(109),char(95),char(98),char(97),char(115), -char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),char(108),char(108),char(105),char(100),char(101), -char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111), -char(114),char(109),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98), -char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(84),char(89),char(80),char(69),char(95),char(0),char(0),char(0),char(99),char(104),char(97),char(114), -char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0), -char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116), -char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114), -char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101), -char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51), -char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68), -char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105), -char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114), -char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116), -char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97), -char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), -char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116), -char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101), -char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101), -char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116), -char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97), -char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104), -char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105), -char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99), -char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110), -char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115), -char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68), -char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101), -char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105), -char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68), -char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110), -char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103), -char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114), -char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116), -char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104), -char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104), -char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111), -char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110), -char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83), -char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104), -char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110), -char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104), -char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117), -char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115), -char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0), -char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111), -char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114), -char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97), -char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), -char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108), -char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108), -char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82), -char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116), -char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0), -char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116), -char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116), -char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), -char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97), -char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116), -char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80), -char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68), -char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110), -char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98), -char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), -char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101), +char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99), +char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116), +char(97),char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105), +char(116),char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110), +char(0),char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100), +char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115), +char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105), +char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111), +char(110),char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0), +char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105), +char(118),char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114), +char(110),char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105), +char(100),char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105), +char(110),char(103),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69), +char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0), +char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97), +char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80), +char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0), +char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114), +char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114), +char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97), +char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115), +char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99), +char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73), +char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111), +char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82), +char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0), +char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104), +char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0), +char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105), +char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116), +char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110), +char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108), +char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99), +char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0), +char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97), +char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95), +char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111), +char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113), +char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108), +char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), +char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110), +char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100), +char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110), +char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105), +char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103), +char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116), +char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70), +char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105), +char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97), +char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109), +char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109), +char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110), +char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(111), +char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115), +char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110), +char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101), +char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108), +char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100), +char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119), +char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118), +char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97), +char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117), +char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97), +char(98),char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121), +char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112), +char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109), +char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101), +char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101), +char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110), +char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109), +char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109), +char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108), +char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109), +char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109), +char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97), +char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103), +char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95), +char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112), +char(97),char(110),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99), +char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70), +char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95), +char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97), +char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117), +char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116), +char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68), +char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111), +char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80), +char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108), +char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101), +char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84), +char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101), +char(97),char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105), +char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105), +char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0), +char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110), +char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117), +char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108), +char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101), +char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114), +char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105), +char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76), +char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112), +char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52), +char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95), +char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103), +char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97), +char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77), +char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114), +char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97), +char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103), +char(117),char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110), +char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115), +char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98), +char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69), +char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117), +char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97), +char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52), +char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105), +char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97), +char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76), +char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114), +char(100),char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115), +char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114), +char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83), +char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105), +char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109), +char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115), +char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0), +char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109), +char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116), +char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93), +char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110), +char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51), +char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93), +char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95), +char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50), +char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42), +char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110), +char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97), +char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102), +char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109), +char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0), +char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67), +char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110), +char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0), +char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115), +char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109), +char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114), +char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67), +char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102), +char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115), +char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73), +char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105), +char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83), +char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120), +char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109), +char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0), +char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115), +char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109), +char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109), +char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109), +char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109), +char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105), +char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118), +char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97), +char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110), +char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109), +char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109), +char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95), +char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101), +char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110), +char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0), +char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110), +char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115), +char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109), +char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97), +char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67), +char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111), +char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109), +char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110), +char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121), +char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95), +char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108), +char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116), +char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111), +char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95), +char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42), +char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95), +char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114), +char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105), +char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109), +char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115), +char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110), +char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111), +char(110),char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116), +char(84),char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111), +char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115), +char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116), +char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109), +char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0), +char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(108),char(105),char(110),char(107), +char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(0),char(109), +char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),char(67),char(111), +char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),char(109),char(95), +char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84), +char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0), +char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116), +char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114), +char(0),char(42),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115), +char(101),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(98),char(97), +char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115), +char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101), +char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(0),char(0),char(0),char(84),char(89),char(80),char(69),char(95),char(0),char(0),char(0), +char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104), +char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102), +char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105), +char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83), +char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99), +char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116), +char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116), +char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117), +char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0), +char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102), +char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104), +char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105), +char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100), +char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104), +char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101), +char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108), +char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116), +char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97), +char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104), +char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114), +char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101), +char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80), +char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101), +char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114), +char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0), +char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101), +char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117), +char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67), +char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67), +char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67), +char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117), +char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103), +char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116), +char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118), +char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99), +char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116), +char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111), +char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115), +char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121), +char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111), +char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70), +char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115), +char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111), +char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114), +char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105), +char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), +char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110), +char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), +char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115), +char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72), +char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67), +char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50), +char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84), +char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102), char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), -char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116), -char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67), -char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111), -char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116), -char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110), -char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97), -char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115), -char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116), -char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110), +char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110), +char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101), +char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71), +char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110), char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105), -char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), -char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114), -char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97), -char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111), -char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111), -char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111), -char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101), -char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), -char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), -char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114), -char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66), -char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116), -char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100), -char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97), -char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97), -char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114), -char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68), -char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97), -char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98), -char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105), -char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66), -char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116), -char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78), -char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0), -char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0), -char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0), -char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0), -char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(64),char(0),char(68),char(0),char(-48),char(1), -char(0),char(1),char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-24),char(1),char(-96),char(3),char(8),char(0),char(52),char(0),char(52),char(0), -char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),char(124),char(1),char(-44),char(0), -char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),char(92),char(0),char(-116),char(0), -char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),char(92),char(1),char(104),char(0), -char(-84),char(1),char(-68),char(2),char(108),char(1),char(-68),char(0),char(100),char(0),char(0),char(0),char(83),char(84),char(82),char(67),char(84),char(0),char(0),char(0), -char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0), -char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0), -char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0), -char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0), -char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0), -char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0), -char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0), -char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0), -char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0), -char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0), -char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0), -char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0), -char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0), -char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0), -char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0), -char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0), -char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0), -char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0), -char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0), -char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0), -char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0), -char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0), -char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0), -char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0), -char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0), -char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0), -char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0), -char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0), -char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0), -char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0), -char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0), -char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0), -char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0), -char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0), -char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0), -char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0), -char(47),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0), -char(4),char(0),char(96),char(0),char(48),char(0),char(5),char(0),char(29),char(0),char(47),char(0),char(13),char(0),char(97),char(0),char(14),char(0),char(98),char(0), -char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),char(49),char(0),char(25),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0), -char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(104),char(0),char(20),char(0),char(105),char(0),char(14),char(0),char(106),char(0), -char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0), -char(8),char(0),char(112),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0), -char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0), -char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(50),char(0),char(25),char(0),char(9),char(0),char(101),char(0), -char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(104),char(0),char(19),char(0),char(105),char(0), -char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0),char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0), -char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0), -char(7),char(0),char(116),char(0),char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0), -char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(2),char(0), -char(52),char(0),char(124),char(0),char(14),char(0),char(125),char(0),char(53),char(0),char(2),char(0),char(54),char(0),char(124),char(0),char(13),char(0),char(125),char(0), -char(55),char(0),char(21),char(0),char(50),char(0),char(126),char(0),char(17),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0), -char(13),char(0),char(-126),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0), -char(13),char(0),char(-122),char(0),char(13),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0), -char(7),char(0),char(-117),char(0),char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0), -char(7),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(56),char(0),char(22),char(0),char(49),char(0),char(126),char(0),char(18),char(0),char(127),char(0), -char(14),char(0),char(-128),char(0),char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(125),char(0), -char(14),char(0),char(-124),char(0),char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0), -char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0), -char(8),char(0),char(-114),char(0),char(8),char(0),char(-113),char(0),char(8),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(0),char(0),char(37),char(0), -char(57),char(0),char(2),char(0),char(4),char(0),char(-110),char(0),char(4),char(0),char(-109),char(0),char(58),char(0),char(13),char(0),char(55),char(0),char(-108),char(0), -char(55),char(0),char(-107),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0), -char(4),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0), -char(7),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(59),char(0),char(13),char(0),char(60),char(0),char(-108),char(0),char(60),char(0),char(-107),char(0), -char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0), -char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0), -char(4),char(0),char(-97),char(0),char(61),char(0),char(14),char(0),char(56),char(0),char(-108),char(0),char(56),char(0),char(-107),char(0),char(0),char(0),char(35),char(0), -char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0), -char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0), -char(0),char(0),char(-96),char(0),char(62),char(0),char(3),char(0),char(59),char(0),char(-95),char(0),char(13),char(0),char(-94),char(0),char(13),char(0),char(-93),char(0), -char(63),char(0),char(3),char(0),char(61),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(64),char(0),char(3),char(0), -char(59),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(65),char(0),char(13),char(0),char(59),char(0),char(-95),char(0), -char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0), -char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0), -char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(66),char(0),char(13),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0), -char(19),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0), -char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0), -char(7),char(0),char(-81),char(0),char(67),char(0),char(14),char(0),char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0), -char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0), -char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0), -char(0),char(0),char(-80),char(0),char(68),char(0),char(10),char(0),char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0), -char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0), -char(8),char(0),char(-81),char(0),char(8),char(0),char(-76),char(0),char(69),char(0),char(11),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0), -char(19),char(0),char(-91),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(7),char(0),char(-83),char(0), -char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-76),char(0),char(0),char(0),char(21),char(0),char(70),char(0),char(9),char(0), -char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0),char(19),char(0),char(-91),char(0),char(13),char(0),char(-75),char(0),char(13),char(0),char(-74),char(0), -char(13),char(0),char(-73),char(0),char(13),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(71),char(0),char(9),char(0), -char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(14),char(0),char(-75),char(0),char(14),char(0),char(-74),char(0), -char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(72),char(0),char(5),char(0), -char(70),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0), -char(73),char(0),char(5),char(0),char(71),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(8),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0), -char(8),char(0),char(-65),char(0),char(74),char(0),char(41),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0),char(19),char(0),char(-91),char(0), -char(13),char(0),char(-75),char(0),char(13),char(0),char(-74),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-62),char(0), -char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(13),char(0),char(-58),char(0),char(13),char(0),char(-57),char(0), -char(13),char(0),char(-56),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),char(0),char(0),char(-53),char(0),char(0),char(0),char(-52),char(0), -char(0),char(0),char(-51),char(0),char(0),char(0),char(-50),char(0),char(0),char(0),char(-49),char(0),char(0),char(0),char(-80),char(0),char(13),char(0),char(-73),char(0), -char(13),char(0),char(-72),char(0),char(13),char(0),char(-48),char(0),char(13),char(0),char(-47),char(0),char(13),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0), -char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(13),char(0),char(-40),char(0), -char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0),char(0),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0), -char(0),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(4),char(0),char(-32),char(0),char(75),char(0),char(41),char(0),char(61),char(0),char(-95),char(0), -char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(14),char(0),char(-75),char(0),char(14),char(0),char(-74),char(0),char(14),char(0),char(-64),char(0), -char(14),char(0),char(-63),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),char(14),char(0),char(-59),char(0), -char(14),char(0),char(-58),char(0),char(14),char(0),char(-57),char(0),char(14),char(0),char(-56),char(0),char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0), -char(0),char(0),char(-53),char(0),char(0),char(0),char(-52),char(0),char(0),char(0),char(-51),char(0),char(0),char(0),char(-50),char(0),char(0),char(0),char(-49),char(0), -char(0),char(0),char(-80),char(0),char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(14),char(0),char(-48),char(0),char(14),char(0),char(-47),char(0), -char(14),char(0),char(-46),char(0),char(14),char(0),char(-45),char(0),char(14),char(0),char(-44),char(0),char(14),char(0),char(-43),char(0),char(14),char(0),char(-42),char(0), -char(14),char(0),char(-41),char(0),char(14),char(0),char(-40),char(0),char(14),char(0),char(-39),char(0),char(14),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0), -char(0),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(0),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(4),char(0),char(-32),char(0), -char(76),char(0),char(9),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0),char(19),char(0),char(-91),char(0),char(7),char(0),char(-75),char(0), -char(7),char(0),char(-74),char(0),char(7),char(0),char(-73),char(0),char(7),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0), -char(77),char(0),char(9),char(0),char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(8),char(0),char(-75),char(0), -char(8),char(0),char(-74),char(0),char(8),char(0),char(-73),char(0),char(8),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0), -char(78),char(0),char(5),char(0),char(58),char(0),char(-95),char(0),char(13),char(0),char(-31),char(0),char(13),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0), -char(0),char(0),char(37),char(0),char(79),char(0),char(4),char(0),char(61),char(0),char(-95),char(0),char(14),char(0),char(-31),char(0),char(14),char(0),char(-30),char(0), -char(8),char(0),char(-29),char(0),char(52),char(0),char(22),char(0),char(8),char(0),char(-28),char(0),char(8),char(0),char(-76),char(0),char(8),char(0),char(111),char(0), -char(8),char(0),char(-27),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0), -char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-19),char(0), -char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),char(4),char(0),char(-15),char(0),char(4),char(0),char(-14),char(0), -char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0), -char(7),char(0),char(-28),char(0),char(7),char(0),char(-76),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(113),char(0), -char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0), -char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0), -char(7),char(0),char(-16),char(0),char(4),char(0),char(-15),char(0),char(4),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0), -char(4),char(0),char(-11),char(0),char(0),char(0),char(37),char(0),char(80),char(0),char(4),char(0),char(7),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0), -char(7),char(0),char(-8),char(0),char(4),char(0),char(79),char(0),char(81),char(0),char(10),char(0),char(80),char(0),char(-7),char(0),char(13),char(0),char(-6),char(0), -char(13),char(0),char(-5),char(0),char(13),char(0),char(-4),char(0),char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(7),char(0),char(-120),char(0), -char(7),char(0),char(-1),char(0),char(4),char(0),char(0),char(1),char(4),char(0),char(53),char(0),char(82),char(0),char(4),char(0),char(80),char(0),char(-7),char(0), -char(4),char(0),char(1),char(1),char(7),char(0),char(2),char(1),char(4),char(0),char(3),char(1),char(83),char(0),char(4),char(0),char(13),char(0),char(-2),char(0), -char(80),char(0),char(-7),char(0),char(4),char(0),char(4),char(1),char(7),char(0),char(5),char(1),char(84),char(0),char(7),char(0),char(13),char(0),char(6),char(1), -char(80),char(0),char(-7),char(0),char(4),char(0),char(7),char(1),char(7),char(0),char(8),char(1),char(7),char(0),char(9),char(1),char(7),char(0),char(10),char(1), -char(4),char(0),char(53),char(0),char(85),char(0),char(6),char(0),char(17),char(0),char(11),char(1),char(13),char(0),char(9),char(1),char(13),char(0),char(12),char(1), -char(60),char(0),char(13),char(1),char(4),char(0),char(14),char(1),char(7),char(0),char(10),char(1),char(86),char(0),char(26),char(0),char(4),char(0),char(15),char(1), -char(7),char(0),char(16),char(1),char(7),char(0),char(-76),char(0),char(7),char(0),char(17),char(1),char(7),char(0),char(18),char(1),char(7),char(0),char(19),char(1), -char(7),char(0),char(20),char(1),char(7),char(0),char(21),char(1),char(7),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1), -char(7),char(0),char(25),char(1),char(7),char(0),char(26),char(1),char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1), -char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(7),char(0),char(32),char(1),char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1), -char(4),char(0),char(35),char(1),char(4),char(0),char(36),char(1),char(4),char(0),char(37),char(1),char(4),char(0),char(38),char(1),char(4),char(0),char(118),char(0), -char(87),char(0),char(12),char(0),char(17),char(0),char(39),char(1),char(17),char(0),char(40),char(1),char(17),char(0),char(41),char(1),char(13),char(0),char(42),char(1), -char(13),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(4),char(0),char(46),char(1),char(4),char(0),char(47),char(1), -char(4),char(0),char(48),char(1),char(7),char(0),char(8),char(1),char(4),char(0),char(53),char(0),char(88),char(0),char(27),char(0),char(19),char(0),char(49),char(1), -char(17),char(0),char(50),char(1),char(17),char(0),char(51),char(1),char(13),char(0),char(42),char(1),char(13),char(0),char(52),char(1),char(13),char(0),char(53),char(1), -char(13),char(0),char(54),char(1),char(13),char(0),char(55),char(1),char(13),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1), -char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),char(4),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1), -char(4),char(0),char(64),char(1),char(4),char(0),char(65),char(1),char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1), -char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),char(7),char(0),char(71),char(1),char(4),char(0),char(72),char(1),char(4),char(0),char(73),char(1), -char(4),char(0),char(74),char(1),char(89),char(0),char(12),char(0),char(9),char(0),char(75),char(1),char(9),char(0),char(76),char(1),char(13),char(0),char(77),char(1), -char(7),char(0),char(78),char(1),char(7),char(0),char(-24),char(0),char(7),char(0),char(79),char(1),char(4),char(0),char(80),char(1),char(13),char(0),char(81),char(1), -char(4),char(0),char(82),char(1),char(4),char(0),char(83),char(1),char(4),char(0),char(84),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(19),char(0), -char(50),char(0),char(126),char(0),char(87),char(0),char(85),char(1),char(80),char(0),char(86),char(1),char(81),char(0),char(87),char(1),char(82),char(0),char(88),char(1), -char(83),char(0),char(89),char(1),char(84),char(0),char(90),char(1),char(85),char(0),char(91),char(1),char(88),char(0),char(92),char(1),char(89),char(0),char(93),char(1), -char(4),char(0),char(94),char(1),char(4),char(0),char(60),char(1),char(4),char(0),char(95),char(1),char(4),char(0),char(96),char(1),char(4),char(0),char(97),char(1), -char(4),char(0),char(98),char(1),char(4),char(0),char(99),char(1),char(4),char(0),char(100),char(1),char(86),char(0),char(101),char(1),char(91),char(0),char(17),char(0), -char(16),char(0),char(102),char(1),char(14),char(0),char(103),char(1),char(14),char(0),char(104),char(1),char(14),char(0),char(105),char(1),char(14),char(0),char(106),char(1), -char(0),char(0),char(107),char(1),char(0),char(0),char(108),char(1),char(49),char(0),char(109),char(1),char(14),char(0),char(110),char(1),char(8),char(0),char(111),char(1), -char(4),char(0),char(112),char(1),char(4),char(0),char(84),char(1),char(4),char(0),char(113),char(1),char(4),char(0),char(114),char(1),char(8),char(0),char(115),char(1), -char(8),char(0),char(116),char(1),char(8),char(0),char(117),char(1),char(92),char(0),char(17),char(0),char(15),char(0),char(102),char(1),char(13),char(0),char(103),char(1), -char(13),char(0),char(104),char(1),char(13),char(0),char(105),char(1),char(13),char(0),char(106),char(1),char(0),char(0),char(107),char(1),char(0),char(0),char(108),char(1), -char(50),char(0),char(109),char(1),char(13),char(0),char(110),char(1),char(4),char(0),char(113),char(1),char(7),char(0),char(111),char(1),char(4),char(0),char(112),char(1), -char(4),char(0),char(84),char(1),char(7),char(0),char(115),char(1),char(7),char(0),char(116),char(1),char(7),char(0),char(117),char(1),char(4),char(0),char(114),char(1), -char(93),char(0),char(8),char(0),char(0),char(0),char(118),char(1),char(91),char(0),char(88),char(1),char(49),char(0),char(119),char(1),char(20),char(0),char(120),char(1), -char(14),char(0),char(121),char(1),char(4),char(0),char(95),char(1),char(8),char(0),char(122),char(1),char(0),char(0),char(37),char(0),char(94),char(0),char(7),char(0), -char(0),char(0),char(118),char(1),char(92),char(0),char(88),char(1),char(50),char(0),char(119),char(1),char(19),char(0),char(120),char(1),char(13),char(0),char(121),char(1), -char(7),char(0),char(122),char(1),char(4),char(0),char(95),char(1),}; +char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100), +char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83), +char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108), +char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111), +char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83), +char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0), +char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102), +char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111), +char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84), +char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110), +char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110), +char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101), +char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107), +char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111), +char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117), +char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0), +char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0), +char(8),char(0),char(0),char(0),char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0), +char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0), +char(52),char(0),char(52),char(0),char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0), +char(60),char(0),char(56),char(0),char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(64),char(0), +char(68),char(0),char(-32),char(1),char(8),char(1),char(-104),char(0),char(88),char(0),char(-72),char(0),char(104),char(0),char(-16),char(1),char(-80),char(3),char(8),char(0), +char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1), +char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1), +char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0), +char(92),char(1),char(104),char(0),char(-76),char(1),char(-48),char(2),char(120),char(1),char(-64),char(0),char(100),char(0),char(0),char(0),char(83),char(84),char(82),char(67), +char(84),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0), +char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0), +char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0), +char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0), +char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0), +char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0), +char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0), +char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0), +char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0), +char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0), +char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0), +char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0), +char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0), +char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0), +char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0), +char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0), +char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0), +char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0), +char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0), +char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0), +char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0), +char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0), +char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0), +char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0), +char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0), +char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0), +char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0), +char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0), +char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0), +char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0), +char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0), +char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0), +char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0), +char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0), +char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0), +char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0), +char(0),char(0),char(37),char(0),char(47),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(13),char(0),char(39),char(0), +char(7),char(0),char(43),char(0),char(4),char(0),char(96),char(0),char(48),char(0),char(5),char(0),char(29),char(0),char(47),char(0),char(13),char(0),char(97),char(0), +char(14),char(0),char(98),char(0),char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),char(49),char(0),char(27),char(0),char(9),char(0),char(101),char(0), +char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(104),char(0),char(20),char(0),char(105),char(0), +char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0), +char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0), +char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),char(8),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0), +char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0), +char(0),char(0),char(37),char(0),char(50),char(0),char(27),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0), +char(0),char(0),char(35),char(0),char(19),char(0),char(104),char(0),char(19),char(0),char(105),char(0),char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0), +char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0), +char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0), +char(7),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0), +char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0), +char(8),char(0),char(126),char(0),char(8),char(0),char(127),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(-128),char(0),char(8),char(0),char(115),char(0), +char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(8),char(0),char(-124),char(0),char(8),char(0),char(-123),char(0), +char(8),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0), +char(8),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0),char(4),char(0),char(-115),char(0),char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0), +char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(52),char(0),char(22),char(0),char(7),char(0),char(126),char(0),char(7),char(0),char(127),char(0), +char(7),char(0),char(111),char(0),char(7),char(0),char(-128),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0), +char(7),char(0),char(-125),char(0),char(7),char(0),char(-124),char(0),char(7),char(0),char(-123),char(0),char(7),char(0),char(-122),char(0),char(7),char(0),char(-121),char(0), +char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0), +char(4),char(0),char(-115),char(0),char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0), +char(53),char(0),char(2),char(0),char(51),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(54),char(0),char(2),char(0),char(52),char(0),char(-111),char(0), +char(13),char(0),char(-110),char(0),char(55),char(0),char(21),char(0),char(50),char(0),char(-109),char(0),char(17),char(0),char(-108),char(0),char(13),char(0),char(-107),char(0), +char(13),char(0),char(-106),char(0),char(13),char(0),char(-105),char(0),char(13),char(0),char(-104),char(0),char(13),char(0),char(-110),char(0),char(13),char(0),char(-103),char(0), +char(13),char(0),char(-102),char(0),char(13),char(0),char(-101),char(0),char(13),char(0),char(-100),char(0),char(7),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0), +char(7),char(0),char(-97),char(0),char(7),char(0),char(-96),char(0),char(7),char(0),char(-95),char(0),char(7),char(0),char(-94),char(0),char(7),char(0),char(-93),char(0), +char(7),char(0),char(-92),char(0),char(7),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(56),char(0),char(22),char(0),char(49),char(0),char(-109),char(0), +char(18),char(0),char(-108),char(0),char(14),char(0),char(-107),char(0),char(14),char(0),char(-106),char(0),char(14),char(0),char(-105),char(0),char(14),char(0),char(-104),char(0), +char(14),char(0),char(-110),char(0),char(14),char(0),char(-103),char(0),char(14),char(0),char(-102),char(0),char(14),char(0),char(-101),char(0),char(14),char(0),char(-100),char(0), +char(8),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(8),char(0),char(-97),char(0),char(8),char(0),char(-96),char(0),char(8),char(0),char(-95),char(0), +char(8),char(0),char(-94),char(0),char(8),char(0),char(-93),char(0),char(8),char(0),char(-92),char(0),char(8),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0), +char(0),char(0),char(37),char(0),char(57),char(0),char(2),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(58),char(0),char(13),char(0), +char(55),char(0),char(-87),char(0),char(55),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0), +char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0), +char(4),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(59),char(0),char(13),char(0),char(60),char(0),char(-87),char(0), +char(60),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0), +char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0), +char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(61),char(0),char(14),char(0),char(56),char(0),char(-87),char(0),char(56),char(0),char(-86),char(0), +char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0), +char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0), +char(4),char(0),char(-76),char(0),char(0),char(0),char(-75),char(0),char(62),char(0),char(3),char(0),char(59),char(0),char(-74),char(0),char(13),char(0),char(-73),char(0), +char(13),char(0),char(-72),char(0),char(63),char(0),char(3),char(0),char(61),char(0),char(-74),char(0),char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0), +char(64),char(0),char(3),char(0),char(59),char(0),char(-74),char(0),char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(65),char(0),char(13),char(0), +char(59),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0), +char(4),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),char(7),char(0),char(-63),char(0), +char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(66),char(0),char(13),char(0),char(59),char(0),char(-74),char(0), +char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0), +char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0), +char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(67),char(0),char(14),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0), +char(20),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0), +char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0), +char(8),char(0),char(-60),char(0),char(0),char(0),char(-59),char(0),char(68),char(0),char(10),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0), +char(20),char(0),char(-70),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-62),char(0), +char(8),char(0),char(-61),char(0),char(8),char(0),char(-60),char(0),char(8),char(0),char(127),char(0),char(69),char(0),char(11),char(0),char(59),char(0),char(-74),char(0), +char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0), +char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(127),char(0),char(0),char(0),char(21),char(0), +char(70),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0), +char(13),char(0),char(-54),char(0),char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0), +char(71),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(14),char(0),char(-55),char(0), +char(14),char(0),char(-54),char(0),char(14),char(0),char(-53),char(0),char(14),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0), +char(72),char(0),char(5),char(0),char(70),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(7),char(0),char(-46),char(0), +char(7),char(0),char(-45),char(0),char(73),char(0),char(5),char(0),char(71),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),char(8),char(0),char(-47),char(0), +char(8),char(0),char(-46),char(0),char(8),char(0),char(-45),char(0),char(74),char(0),char(41),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0), +char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0), +char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(13),char(0),char(-40),char(0),char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0), +char(13),char(0),char(-37),char(0),char(13),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),char(13),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0), +char(0),char(0),char(-32),char(0),char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0),char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0), +char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),char(13),char(0),char(-28),char(0),char(13),char(0),char(-27),char(0),char(13),char(0),char(-26),char(0), +char(13),char(0),char(-25),char(0),char(13),char(0),char(-24),char(0),char(13),char(0),char(-23),char(0),char(13),char(0),char(-22),char(0),char(13),char(0),char(-21),char(0), +char(13),char(0),char(-20),char(0),char(13),char(0),char(-19),char(0),char(13),char(0),char(-18),char(0),char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0), +char(0),char(0),char(-15),char(0),char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),char(75),char(0),char(41),char(0), +char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0), +char(14),char(0),char(-44),char(0),char(14),char(0),char(-43),char(0),char(14),char(0),char(-42),char(0),char(14),char(0),char(-41),char(0),char(14),char(0),char(-40),char(0), +char(14),char(0),char(-39),char(0),char(14),char(0),char(-38),char(0),char(14),char(0),char(-37),char(0),char(14),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0), +char(14),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(0),char(0),char(-32),char(0),char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0), +char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0),char(14),char(0),char(-53),char(0),char(14),char(0),char(-52),char(0),char(14),char(0),char(-28),char(0), +char(14),char(0),char(-27),char(0),char(14),char(0),char(-26),char(0),char(14),char(0),char(-25),char(0),char(14),char(0),char(-24),char(0),char(14),char(0),char(-23),char(0), +char(14),char(0),char(-22),char(0),char(14),char(0),char(-21),char(0),char(14),char(0),char(-20),char(0),char(14),char(0),char(-19),char(0),char(14),char(0),char(-18),char(0), +char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0),char(0),char(0),char(-15),char(0),char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0), +char(4),char(0),char(-12),char(0),char(76),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0), +char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0), +char(4),char(0),char(-50),char(0),char(77),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0), +char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0), +char(4),char(0),char(-50),char(0),char(78),char(0),char(5),char(0),char(58),char(0),char(-74),char(0),char(13),char(0),char(-11),char(0),char(13),char(0),char(-10),char(0), +char(7),char(0),char(-9),char(0),char(0),char(0),char(37),char(0),char(79),char(0),char(4),char(0),char(61),char(0),char(-74),char(0),char(14),char(0),char(-11),char(0), +char(14),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),char(80),char(0),char(4),char(0),char(7),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0), +char(7),char(0),char(-6),char(0),char(4),char(0),char(79),char(0),char(81),char(0),char(10),char(0),char(80),char(0),char(-5),char(0),char(13),char(0),char(-4),char(0), +char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(7),char(0),char(-99),char(0), +char(7),char(0),char(1),char(1),char(4),char(0),char(2),char(1),char(4),char(0),char(53),char(0),char(82),char(0),char(4),char(0),char(80),char(0),char(-5),char(0), +char(4),char(0),char(3),char(1),char(7),char(0),char(4),char(1),char(4),char(0),char(5),char(1),char(83),char(0),char(4),char(0),char(13),char(0),char(0),char(1), +char(80),char(0),char(-5),char(0),char(4),char(0),char(6),char(1),char(7),char(0),char(7),char(1),char(84),char(0),char(7),char(0),char(13),char(0),char(8),char(1), +char(80),char(0),char(-5),char(0),char(4),char(0),char(9),char(1),char(7),char(0),char(10),char(1),char(7),char(0),char(11),char(1),char(7),char(0),char(12),char(1), +char(4),char(0),char(53),char(0),char(85),char(0),char(6),char(0),char(17),char(0),char(13),char(1),char(13),char(0),char(11),char(1),char(13),char(0),char(14),char(1), +char(60),char(0),char(15),char(1),char(4),char(0),char(16),char(1),char(7),char(0),char(12),char(1),char(86),char(0),char(26),char(0),char(4),char(0),char(17),char(1), +char(7),char(0),char(18),char(1),char(7),char(0),char(127),char(0),char(7),char(0),char(19),char(1),char(7),char(0),char(20),char(1),char(7),char(0),char(21),char(1), +char(7),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(7),char(0),char(25),char(1),char(7),char(0),char(26),char(1), +char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1), +char(7),char(0),char(32),char(1),char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(7),char(0),char(35),char(1),char(7),char(0),char(36),char(1), +char(4),char(0),char(37),char(1),char(4),char(0),char(38),char(1),char(4),char(0),char(39),char(1),char(4),char(0),char(40),char(1),char(4),char(0),char(120),char(0), +char(87),char(0),char(12),char(0),char(17),char(0),char(41),char(1),char(17),char(0),char(42),char(1),char(17),char(0),char(43),char(1),char(13),char(0),char(44),char(1), +char(13),char(0),char(45),char(1),char(7),char(0),char(46),char(1),char(4),char(0),char(47),char(1),char(4),char(0),char(48),char(1),char(4),char(0),char(49),char(1), +char(4),char(0),char(50),char(1),char(7),char(0),char(10),char(1),char(4),char(0),char(53),char(0),char(88),char(0),char(27),char(0),char(19),char(0),char(51),char(1), +char(17),char(0),char(52),char(1),char(17),char(0),char(53),char(1),char(13),char(0),char(44),char(1),char(13),char(0),char(54),char(1),char(13),char(0),char(55),char(1), +char(13),char(0),char(56),char(1),char(13),char(0),char(57),char(1),char(13),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(7),char(0),char(60),char(1), +char(4),char(0),char(61),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1), +char(4),char(0),char(66),char(1),char(4),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1), +char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(4),char(0),char(74),char(1),char(4),char(0),char(75),char(1), +char(4),char(0),char(76),char(1),char(89),char(0),char(12),char(0),char(9),char(0),char(77),char(1),char(9),char(0),char(78),char(1),char(13),char(0),char(79),char(1), +char(7),char(0),char(80),char(1),char(7),char(0),char(-125),char(0),char(7),char(0),char(81),char(1),char(4),char(0),char(82),char(1),char(13),char(0),char(83),char(1), +char(4),char(0),char(84),char(1),char(4),char(0),char(85),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(19),char(0), +char(50),char(0),char(-109),char(0),char(87),char(0),char(87),char(1),char(80),char(0),char(88),char(1),char(81),char(0),char(89),char(1),char(82),char(0),char(90),char(1), +char(83),char(0),char(91),char(1),char(84),char(0),char(92),char(1),char(85),char(0),char(93),char(1),char(88),char(0),char(94),char(1),char(89),char(0),char(95),char(1), +char(4),char(0),char(96),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(97),char(1),char(4),char(0),char(98),char(1),char(4),char(0),char(99),char(1), +char(4),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(86),char(0),char(103),char(1),char(91),char(0),char(20),char(0), +char(16),char(0),char(104),char(1),char(14),char(0),char(105),char(1),char(14),char(0),char(106),char(1),char(14),char(0),char(107),char(1),char(14),char(0),char(108),char(1), +char(14),char(0),char(109),char(1),char(8),char(0),char(110),char(1),char(4),char(0),char(111),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(112),char(1), +char(4),char(0),char(113),char(1),char(8),char(0),char(114),char(1),char(8),char(0),char(115),char(1),char(8),char(0),char(116),char(1),char(8),char(0),char(117),char(1), +char(8),char(0),char(118),char(1),char(0),char(0),char(119),char(1),char(0),char(0),char(120),char(1),char(49),char(0),char(121),char(1),char(0),char(0),char(122),char(1), +char(92),char(0),char(20),char(0),char(15),char(0),char(104),char(1),char(13),char(0),char(105),char(1),char(13),char(0),char(106),char(1),char(13),char(0),char(107),char(1), +char(13),char(0),char(108),char(1),char(13),char(0),char(109),char(1),char(4),char(0),char(112),char(1),char(7),char(0),char(110),char(1),char(4),char(0),char(111),char(1), +char(4),char(0),char(86),char(1),char(7),char(0),char(114),char(1),char(7),char(0),char(115),char(1),char(7),char(0),char(116),char(1),char(4),char(0),char(113),char(1), +char(7),char(0),char(117),char(1),char(7),char(0),char(118),char(1),char(0),char(0),char(119),char(1),char(0),char(0),char(120),char(1),char(50),char(0),char(121),char(1), +char(0),char(0),char(122),char(1),char(93),char(0),char(9),char(0),char(20),char(0),char(123),char(1),char(14),char(0),char(124),char(1),char(8),char(0),char(125),char(1), +char(0),char(0),char(126),char(1),char(91),char(0),char(90),char(1),char(49),char(0),char(127),char(1),char(0),char(0),char(122),char(1),char(4),char(0),char(97),char(1), +char(0),char(0),char(37),char(0),char(94),char(0),char(7),char(0),char(0),char(0),char(126),char(1),char(92),char(0),char(90),char(1),char(50),char(0),char(127),char(1), +char(19),char(0),char(123),char(1),char(13),char(0),char(124),char(1),char(7),char(0),char(125),char(1),char(4),char(0),char(97),char(1),}; int sBulletDNAlen= sizeof(sBulletDNAstr); char sBulletDNAstr64[]= { -char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(123),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109), +char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-128),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109), char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95), char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111), char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110), @@ -679,499 +685,505 @@ char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),c char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84), char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116), char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109), -char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114), -char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99), -char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114), -char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84), -char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116), -char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108), -char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84), -char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95), -char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105), -char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67), -char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73), -char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108), -char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110), -char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0), -char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97), -char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103), -char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70), -char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101), -char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105), -char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0), -char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101), -char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112), -char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103), -char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103), -char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76), -char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), -char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103), -char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100), -char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117), -char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111), -char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103), -char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110), -char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116), -char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65), -char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101), -char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112), -char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100), -char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97), -char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68), -char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108), -char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100), -char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109), -char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98), -char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104), -char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100), -char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97), -char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109), -char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101), -char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102), -char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), -char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108), -char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101), -char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114), -char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), -char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105), -char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116), -char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111), -char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119), -char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110), -char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(100),char(97),char(109),char(112), -char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109), -char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), -char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105), -char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), -char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110), -char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116), -char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109), -char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110), -char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105), -char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83), -char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103), -char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66), -char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82), -char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95), -char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110), -char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114), -char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110), -char(101),char(97),char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115), -char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105), -char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105), -char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98), -char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83), -char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97), -char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108), -char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115), -char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83), -char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91), -char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109), -char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110), -char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), -char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114), -char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97), -char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), -char(97),char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110), -char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97), -char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115), -char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109), -char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105), -char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114), -char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103), -char(117),char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95), -char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91), -char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116), -char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95), -char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103), -char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79), -char(114),char(100),char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105), -char(115),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109), -char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114), -char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114), -char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109), -char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116), -char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112), -char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95), -char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97), -char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114), -char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108), -char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110), -char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97), -char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109), -char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105), -char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105), -char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101), -char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(105), -char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117), -char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109), -char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105), -char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118), -char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99), -char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114), -char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109), -char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101), -char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95), -char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99), -char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99), -char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52), -char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0), -char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97), -char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111), -char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0), -char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109), -char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118), -char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116), -char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105), -char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109), -char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110), -char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114), -char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101), -char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101), -char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101), -char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109), -char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100), -char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115), -char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111), -char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117), -char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67), -char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109), -char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97), -char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105), -char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116), -char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111), -char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111), -char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97), -char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110), -char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111), -char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0), -char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109), -char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0), -char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91), -char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95), -char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115), -char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109), -char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115), -char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115), -char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115), -char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109), -char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95), -char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0), -char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102), -char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115), -char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70), -char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104), -char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116), -char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95), -char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102), -char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109), -char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111), -char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0), -char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0), -char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100), -char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115), -char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110), -char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109), -char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97), -char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70), -char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97), -char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67), -char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0), -char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97), -char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67), -char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95), -char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102), -char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91), -char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109), -char(91),char(54),char(93),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106), -char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108), -char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109), -char(95),char(108),char(105),char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110), -char(100),char(101),char(120),char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115), -char(86),char(97),char(114),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91), -char(55),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106), -char(111),char(105),char(110),char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(42),char(109),char(95),char(98),char(97),char(115), -char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),char(108),char(108),char(105),char(100),char(101), -char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111), -char(114),char(109),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98), -char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(84),char(89),char(80),char(69),char(95),char(0),char(0),char(0),char(99),char(104),char(97),char(114), -char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0), -char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116), -char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114), -char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101), -char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51), -char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68), -char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105), -char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114), -char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116), -char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97), -char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), -char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116), -char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101), -char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101), -char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116), -char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97), -char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104), -char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105), -char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99), -char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110), -char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115), -char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68), -char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98), -char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101), -char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105), -char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68), -char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110), -char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103), -char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114), -char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116), -char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104), -char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104), -char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111), -char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110), -char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83), -char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104), -char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110), -char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104), -char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117), -char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115), -char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0), -char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111), -char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114), -char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97), -char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), -char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108), -char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108), -char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82), -char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116), -char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0), -char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116), -char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116), -char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), -char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97), -char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116), -char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80), -char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68), -char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110), -char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98), -char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), -char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101), +char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99), +char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116), +char(97),char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105), +char(116),char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110), +char(0),char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100), +char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115), +char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105), +char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111), +char(110),char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0), +char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105), +char(118),char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114), +char(110),char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105), +char(100),char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105), +char(110),char(103),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69), +char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0), +char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97), +char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80), +char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0), +char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114), +char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114), +char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97), +char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115), +char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99), +char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73), +char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111), +char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82), +char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0), +char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104), +char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0), +char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105), +char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116), +char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110), +char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108), +char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99), +char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0), +char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97), +char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95), +char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111), +char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113), +char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108), +char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), +char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110), +char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100), +char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110), +char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105), +char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103), +char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116), +char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70), +char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105), +char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97), +char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109), +char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109), +char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110), +char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(111), +char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115), +char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110), +char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101), +char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108), +char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100), +char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119), +char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118), +char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97), +char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117), +char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97), +char(98),char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121), +char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112), +char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109), +char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101), +char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101), +char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110), +char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109), +char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109), +char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108), +char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109), +char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109), +char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97), +char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103), +char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95), +char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112), +char(97),char(110),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99), +char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70), +char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95), +char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97), +char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117), +char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116), +char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68), +char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111), +char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80), +char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108), +char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101), +char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84), +char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101), +char(97),char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105), +char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105), +char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0), +char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110), +char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117), +char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108), +char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101), +char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114), +char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105), +char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76), +char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112), +char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52), +char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95), +char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103), +char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97), +char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77), +char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114), +char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97), +char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103), +char(117),char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110), +char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115), +char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98), +char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69), +char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117), +char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97), +char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52), +char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105), +char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97), +char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76), +char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114), +char(100),char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115), +char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114), +char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83), +char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105), +char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109), +char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115), +char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0), +char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109), +char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116), +char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93), +char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110), +char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51), +char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93), +char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95), +char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50), +char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42), +char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110), +char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97), +char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102), +char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109), +char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0), +char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67), +char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110), +char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0), +char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115), +char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109), +char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114), +char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67), +char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102), +char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115), +char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73), +char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105), +char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83), +char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120), +char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109), +char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0), +char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115), +char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109), +char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109), +char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109), +char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109), +char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105), +char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118), +char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97), +char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110), +char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109), +char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109), +char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95), +char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101), +char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110), +char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0), +char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110), +char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115), +char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109), +char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97), +char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67), +char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111), +char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109), +char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110), +char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121), +char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95), +char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108), +char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116), +char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111), +char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95), +char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42), +char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95), +char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114), +char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105), +char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109), +char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115), +char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110), +char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111), +char(110),char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116), +char(84),char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111), +char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115), +char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116), +char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109), +char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0), +char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(108),char(105),char(110),char(107), +char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(0),char(109), +char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),char(67),char(111), +char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),char(109),char(95), +char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84), +char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0), +char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116), +char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114), +char(0),char(42),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115), +char(101),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(98),char(97), +char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115), +char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101), +char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(0),char(0),char(0),char(84),char(89),char(80),char(69),char(95),char(0),char(0),char(0), +char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104), +char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102), +char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105), +char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83), +char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99), +char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116), +char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116), +char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117), +char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0), +char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102), +char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104), +char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105), +char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100), +char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104), +char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101), +char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108), +char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116), +char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97), +char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104), +char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114), +char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101), +char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80), +char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101), +char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114), +char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0), +char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101), +char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117), +char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67), +char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67), +char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67), +char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117), +char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103), +char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116), +char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118), +char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99), +char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116), +char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111), +char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115), +char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121), +char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111), +char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70), +char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115), +char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111), +char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114), +char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105), +char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), +char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110), +char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), +char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115), +char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72), +char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67), +char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50), +char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84), +char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102), char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), -char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116), -char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67), -char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111), -char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116), -char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110), -char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97), -char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115), -char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116), -char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110), +char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110), +char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101), +char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71), +char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110), char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105), -char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), -char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114), -char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97), -char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111), -char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111), -char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111), -char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101), -char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), -char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), -char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114), -char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66), -char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116), -char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100), -char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97), -char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97), -char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114), -char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68), -char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97), -char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97), -char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98), -char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105), -char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66), -char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116), -char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78), -char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0), -char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0), -char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0), -char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0), -char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(72),char(0),char(80),char(0),char(-32),char(1), -char(16),char(1),char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-8),char(1),char(-80),char(3),char(8),char(0),char(64),char(0),char(64),char(0), -char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),char(-120),char(1),char(-32),char(0), -char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),char(104),char(0),char(-104),char(0), -char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),char(104),char(1),char(112),char(0), -char(-32),char(1),char(-56),char(2),char(120),char(1),char(-56),char(0),char(112),char(0),char(0),char(0),char(83),char(84),char(82),char(67),char(84),char(0),char(0),char(0), -char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0), -char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0), -char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0), -char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0), -char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0), -char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0), -char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0), -char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0), -char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0), -char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0), -char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0), -char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0), -char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0), -char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0), -char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0), -char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0), -char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0), -char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0), -char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0), -char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0), -char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0), -char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0), -char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0), -char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0), -char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0), -char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0), -char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0), -char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0), -char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0), -char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0), -char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0), -char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0), -char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0), -char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0), -char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0), -char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0), -char(47),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0), -char(4),char(0),char(96),char(0),char(48),char(0),char(5),char(0),char(29),char(0),char(47),char(0),char(13),char(0),char(97),char(0),char(14),char(0),char(98),char(0), -char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),char(49),char(0),char(25),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0), -char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(104),char(0),char(20),char(0),char(105),char(0),char(14),char(0),char(106),char(0), -char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0), -char(8),char(0),char(112),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0), -char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0), -char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(50),char(0),char(25),char(0),char(9),char(0),char(101),char(0), -char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(104),char(0),char(19),char(0),char(105),char(0), -char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0),char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0), -char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0), -char(7),char(0),char(116),char(0),char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0), -char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(2),char(0), -char(52),char(0),char(124),char(0),char(14),char(0),char(125),char(0),char(53),char(0),char(2),char(0),char(54),char(0),char(124),char(0),char(13),char(0),char(125),char(0), -char(55),char(0),char(21),char(0),char(50),char(0),char(126),char(0),char(17),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0), -char(13),char(0),char(-126),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0), -char(13),char(0),char(-122),char(0),char(13),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0), -char(7),char(0),char(-117),char(0),char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0), -char(7),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(56),char(0),char(22),char(0),char(49),char(0),char(126),char(0),char(18),char(0),char(127),char(0), -char(14),char(0),char(-128),char(0),char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(125),char(0), -char(14),char(0),char(-124),char(0),char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0), -char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0), -char(8),char(0),char(-114),char(0),char(8),char(0),char(-113),char(0),char(8),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(0),char(0),char(37),char(0), -char(57),char(0),char(2),char(0),char(4),char(0),char(-110),char(0),char(4),char(0),char(-109),char(0),char(58),char(0),char(13),char(0),char(55),char(0),char(-108),char(0), -char(55),char(0),char(-107),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0), -char(4),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0), -char(7),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(59),char(0),char(13),char(0),char(60),char(0),char(-108),char(0),char(60),char(0),char(-107),char(0), -char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0), -char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0), -char(4),char(0),char(-97),char(0),char(61),char(0),char(14),char(0),char(56),char(0),char(-108),char(0),char(56),char(0),char(-107),char(0),char(0),char(0),char(35),char(0), -char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0), -char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0), -char(0),char(0),char(-96),char(0),char(62),char(0),char(3),char(0),char(59),char(0),char(-95),char(0),char(13),char(0),char(-94),char(0),char(13),char(0),char(-93),char(0), -char(63),char(0),char(3),char(0),char(61),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(64),char(0),char(3),char(0), -char(59),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(65),char(0),char(13),char(0),char(59),char(0),char(-95),char(0), -char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0), -char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0), -char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(66),char(0),char(13),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0), -char(19),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0), -char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0), -char(7),char(0),char(-81),char(0),char(67),char(0),char(14),char(0),char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0), -char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0), -char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0), -char(0),char(0),char(-80),char(0),char(68),char(0),char(10),char(0),char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0), -char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0), -char(8),char(0),char(-81),char(0),char(8),char(0),char(-76),char(0),char(69),char(0),char(11),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0), -char(19),char(0),char(-91),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(7),char(0),char(-83),char(0), -char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-76),char(0),char(0),char(0),char(21),char(0),char(70),char(0),char(9),char(0), -char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0),char(19),char(0),char(-91),char(0),char(13),char(0),char(-75),char(0),char(13),char(0),char(-74),char(0), -char(13),char(0),char(-73),char(0),char(13),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(71),char(0),char(9),char(0), -char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(14),char(0),char(-75),char(0),char(14),char(0),char(-74),char(0), -char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(72),char(0),char(5),char(0), -char(70),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0), -char(73),char(0),char(5),char(0),char(71),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(8),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0), -char(8),char(0),char(-65),char(0),char(74),char(0),char(41),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0),char(19),char(0),char(-91),char(0), -char(13),char(0),char(-75),char(0),char(13),char(0),char(-74),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-62),char(0), -char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(13),char(0),char(-58),char(0),char(13),char(0),char(-57),char(0), -char(13),char(0),char(-56),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),char(0),char(0),char(-53),char(0),char(0),char(0),char(-52),char(0), -char(0),char(0),char(-51),char(0),char(0),char(0),char(-50),char(0),char(0),char(0),char(-49),char(0),char(0),char(0),char(-80),char(0),char(13),char(0),char(-73),char(0), -char(13),char(0),char(-72),char(0),char(13),char(0),char(-48),char(0),char(13),char(0),char(-47),char(0),char(13),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0), -char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(13),char(0),char(-40),char(0), -char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0),char(0),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0), -char(0),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(4),char(0),char(-32),char(0),char(75),char(0),char(41),char(0),char(61),char(0),char(-95),char(0), -char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(14),char(0),char(-75),char(0),char(14),char(0),char(-74),char(0),char(14),char(0),char(-64),char(0), -char(14),char(0),char(-63),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),char(14),char(0),char(-59),char(0), -char(14),char(0),char(-58),char(0),char(14),char(0),char(-57),char(0),char(14),char(0),char(-56),char(0),char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0), -char(0),char(0),char(-53),char(0),char(0),char(0),char(-52),char(0),char(0),char(0),char(-51),char(0),char(0),char(0),char(-50),char(0),char(0),char(0),char(-49),char(0), -char(0),char(0),char(-80),char(0),char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(14),char(0),char(-48),char(0),char(14),char(0),char(-47),char(0), -char(14),char(0),char(-46),char(0),char(14),char(0),char(-45),char(0),char(14),char(0),char(-44),char(0),char(14),char(0),char(-43),char(0),char(14),char(0),char(-42),char(0), -char(14),char(0),char(-41),char(0),char(14),char(0),char(-40),char(0),char(14),char(0),char(-39),char(0),char(14),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0), -char(0),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(0),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(4),char(0),char(-32),char(0), -char(76),char(0),char(9),char(0),char(59),char(0),char(-95),char(0),char(19),char(0),char(-92),char(0),char(19),char(0),char(-91),char(0),char(7),char(0),char(-75),char(0), -char(7),char(0),char(-74),char(0),char(7),char(0),char(-73),char(0),char(7),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0), -char(77),char(0),char(9),char(0),char(61),char(0),char(-95),char(0),char(20),char(0),char(-92),char(0),char(20),char(0),char(-91),char(0),char(8),char(0),char(-75),char(0), -char(8),char(0),char(-74),char(0),char(8),char(0),char(-73),char(0),char(8),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0), -char(78),char(0),char(5),char(0),char(58),char(0),char(-95),char(0),char(13),char(0),char(-31),char(0),char(13),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0), -char(0),char(0),char(37),char(0),char(79),char(0),char(4),char(0),char(61),char(0),char(-95),char(0),char(14),char(0),char(-31),char(0),char(14),char(0),char(-30),char(0), -char(8),char(0),char(-29),char(0),char(52),char(0),char(22),char(0),char(8),char(0),char(-28),char(0),char(8),char(0),char(-76),char(0),char(8),char(0),char(111),char(0), -char(8),char(0),char(-27),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0), -char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-19),char(0), -char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),char(4),char(0),char(-15),char(0),char(4),char(0),char(-14),char(0), -char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0), -char(7),char(0),char(-28),char(0),char(7),char(0),char(-76),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(113),char(0), -char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0), -char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0), -char(7),char(0),char(-16),char(0),char(4),char(0),char(-15),char(0),char(4),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0), -char(4),char(0),char(-11),char(0),char(0),char(0),char(37),char(0),char(80),char(0),char(4),char(0),char(7),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0), -char(7),char(0),char(-8),char(0),char(4),char(0),char(79),char(0),char(81),char(0),char(10),char(0),char(80),char(0),char(-7),char(0),char(13),char(0),char(-6),char(0), -char(13),char(0),char(-5),char(0),char(13),char(0),char(-4),char(0),char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(7),char(0),char(-120),char(0), -char(7),char(0),char(-1),char(0),char(4),char(0),char(0),char(1),char(4),char(0),char(53),char(0),char(82),char(0),char(4),char(0),char(80),char(0),char(-7),char(0), -char(4),char(0),char(1),char(1),char(7),char(0),char(2),char(1),char(4),char(0),char(3),char(1),char(83),char(0),char(4),char(0),char(13),char(0),char(-2),char(0), -char(80),char(0),char(-7),char(0),char(4),char(0),char(4),char(1),char(7),char(0),char(5),char(1),char(84),char(0),char(7),char(0),char(13),char(0),char(6),char(1), -char(80),char(0),char(-7),char(0),char(4),char(0),char(7),char(1),char(7),char(0),char(8),char(1),char(7),char(0),char(9),char(1),char(7),char(0),char(10),char(1), -char(4),char(0),char(53),char(0),char(85),char(0),char(6),char(0),char(17),char(0),char(11),char(1),char(13),char(0),char(9),char(1),char(13),char(0),char(12),char(1), -char(60),char(0),char(13),char(1),char(4),char(0),char(14),char(1),char(7),char(0),char(10),char(1),char(86),char(0),char(26),char(0),char(4),char(0),char(15),char(1), -char(7),char(0),char(16),char(1),char(7),char(0),char(-76),char(0),char(7),char(0),char(17),char(1),char(7),char(0),char(18),char(1),char(7),char(0),char(19),char(1), -char(7),char(0),char(20),char(1),char(7),char(0),char(21),char(1),char(7),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1), -char(7),char(0),char(25),char(1),char(7),char(0),char(26),char(1),char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1), -char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(7),char(0),char(32),char(1),char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1), -char(4),char(0),char(35),char(1),char(4),char(0),char(36),char(1),char(4),char(0),char(37),char(1),char(4),char(0),char(38),char(1),char(4),char(0),char(118),char(0), -char(87),char(0),char(12),char(0),char(17),char(0),char(39),char(1),char(17),char(0),char(40),char(1),char(17),char(0),char(41),char(1),char(13),char(0),char(42),char(1), -char(13),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(4),char(0),char(46),char(1),char(4),char(0),char(47),char(1), -char(4),char(0),char(48),char(1),char(7),char(0),char(8),char(1),char(4),char(0),char(53),char(0),char(88),char(0),char(27),char(0),char(19),char(0),char(49),char(1), -char(17),char(0),char(50),char(1),char(17),char(0),char(51),char(1),char(13),char(0),char(42),char(1),char(13),char(0),char(52),char(1),char(13),char(0),char(53),char(1), -char(13),char(0),char(54),char(1),char(13),char(0),char(55),char(1),char(13),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1), -char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),char(4),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1), -char(4),char(0),char(64),char(1),char(4),char(0),char(65),char(1),char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1), -char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),char(7),char(0),char(71),char(1),char(4),char(0),char(72),char(1),char(4),char(0),char(73),char(1), -char(4),char(0),char(74),char(1),char(89),char(0),char(12),char(0),char(9),char(0),char(75),char(1),char(9),char(0),char(76),char(1),char(13),char(0),char(77),char(1), -char(7),char(0),char(78),char(1),char(7),char(0),char(-24),char(0),char(7),char(0),char(79),char(1),char(4),char(0),char(80),char(1),char(13),char(0),char(81),char(1), -char(4),char(0),char(82),char(1),char(4),char(0),char(83),char(1),char(4),char(0),char(84),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(19),char(0), -char(50),char(0),char(126),char(0),char(87),char(0),char(85),char(1),char(80),char(0),char(86),char(1),char(81),char(0),char(87),char(1),char(82),char(0),char(88),char(1), -char(83),char(0),char(89),char(1),char(84),char(0),char(90),char(1),char(85),char(0),char(91),char(1),char(88),char(0),char(92),char(1),char(89),char(0),char(93),char(1), -char(4),char(0),char(94),char(1),char(4),char(0),char(60),char(1),char(4),char(0),char(95),char(1),char(4),char(0),char(96),char(1),char(4),char(0),char(97),char(1), -char(4),char(0),char(98),char(1),char(4),char(0),char(99),char(1),char(4),char(0),char(100),char(1),char(86),char(0),char(101),char(1),char(91),char(0),char(17),char(0), -char(16),char(0),char(102),char(1),char(14),char(0),char(103),char(1),char(14),char(0),char(104),char(1),char(14),char(0),char(105),char(1),char(14),char(0),char(106),char(1), -char(0),char(0),char(107),char(1),char(0),char(0),char(108),char(1),char(49),char(0),char(109),char(1),char(14),char(0),char(110),char(1),char(8),char(0),char(111),char(1), -char(4),char(0),char(112),char(1),char(4),char(0),char(84),char(1),char(4),char(0),char(113),char(1),char(4),char(0),char(114),char(1),char(8),char(0),char(115),char(1), -char(8),char(0),char(116),char(1),char(8),char(0),char(117),char(1),char(92),char(0),char(17),char(0),char(15),char(0),char(102),char(1),char(13),char(0),char(103),char(1), -char(13),char(0),char(104),char(1),char(13),char(0),char(105),char(1),char(13),char(0),char(106),char(1),char(0),char(0),char(107),char(1),char(0),char(0),char(108),char(1), -char(50),char(0),char(109),char(1),char(13),char(0),char(110),char(1),char(4),char(0),char(113),char(1),char(7),char(0),char(111),char(1),char(4),char(0),char(112),char(1), -char(4),char(0),char(84),char(1),char(7),char(0),char(115),char(1),char(7),char(0),char(116),char(1),char(7),char(0),char(117),char(1),char(4),char(0),char(114),char(1), -char(93),char(0),char(8),char(0),char(0),char(0),char(118),char(1),char(91),char(0),char(88),char(1),char(49),char(0),char(119),char(1),char(20),char(0),char(120),char(1), -char(14),char(0),char(121),char(1),char(4),char(0),char(95),char(1),char(8),char(0),char(122),char(1),char(0),char(0),char(37),char(0),char(94),char(0),char(7),char(0), -char(0),char(0),char(118),char(1),char(92),char(0),char(88),char(1),char(50),char(0),char(119),char(1),char(19),char(0),char(120),char(1),char(13),char(0),char(121),char(1), -char(7),char(0),char(122),char(1),char(4),char(0),char(95),char(1),}; +char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100), +char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83), +char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108), +char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105), +char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111), +char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83), +char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0), +char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102), +char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111), +char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84), +char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110), +char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110), +char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101), +char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107), +char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111), +char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117), +char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0), +char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0), +char(8),char(0),char(0),char(0),char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0), +char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0), +char(56),char(0),char(56),char(0),char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0), +char(80),char(0),char(72),char(0),char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(72),char(0), +char(80),char(0),char(-16),char(1),char(24),char(1),char(-104),char(0),char(88),char(0),char(-72),char(0),char(104),char(0),char(0),char(2),char(-64),char(3),char(8),char(0), +char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1), +char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1), +char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0), +char(104),char(1),char(112),char(0),char(-24),char(1),char(-32),char(2),char(-120),char(1),char(-48),char(0),char(112),char(0),char(0),char(0),char(83),char(84),char(82),char(67), +char(84),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0), +char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0), +char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0), +char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0), +char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0), +char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0), +char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0), +char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0), +char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0), +char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0), +char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0), +char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0), +char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0), +char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0), +char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0), +char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0), +char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0), +char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0), +char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0), +char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0), +char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0), +char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0), +char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0), +char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0), +char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0), +char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0), +char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0), +char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0), +char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0), +char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0), +char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0), +char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0), +char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0), +char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0), +char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0), +char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0), +char(0),char(0),char(37),char(0),char(47),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(13),char(0),char(39),char(0), +char(7),char(0),char(43),char(0),char(4),char(0),char(96),char(0),char(48),char(0),char(5),char(0),char(29),char(0),char(47),char(0),char(13),char(0),char(97),char(0), +char(14),char(0),char(98),char(0),char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),char(49),char(0),char(27),char(0),char(9),char(0),char(101),char(0), +char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(104),char(0),char(20),char(0),char(105),char(0), +char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0), +char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0), +char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),char(8),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0), +char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0), +char(0),char(0),char(37),char(0),char(50),char(0),char(27),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0), +char(0),char(0),char(35),char(0),char(19),char(0),char(104),char(0),char(19),char(0),char(105),char(0),char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0), +char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0), +char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0), +char(7),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0), +char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0), +char(8),char(0),char(126),char(0),char(8),char(0),char(127),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(-128),char(0),char(8),char(0),char(115),char(0), +char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(8),char(0),char(-124),char(0),char(8),char(0),char(-123),char(0), +char(8),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0), +char(8),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0),char(4),char(0),char(-115),char(0),char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0), +char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(52),char(0),char(22),char(0),char(7),char(0),char(126),char(0),char(7),char(0),char(127),char(0), +char(7),char(0),char(111),char(0),char(7),char(0),char(-128),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0), +char(7),char(0),char(-125),char(0),char(7),char(0),char(-124),char(0),char(7),char(0),char(-123),char(0),char(7),char(0),char(-122),char(0),char(7),char(0),char(-121),char(0), +char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0), +char(4),char(0),char(-115),char(0),char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0), +char(53),char(0),char(2),char(0),char(51),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(54),char(0),char(2),char(0),char(52),char(0),char(-111),char(0), +char(13),char(0),char(-110),char(0),char(55),char(0),char(21),char(0),char(50),char(0),char(-109),char(0),char(17),char(0),char(-108),char(0),char(13),char(0),char(-107),char(0), +char(13),char(0),char(-106),char(0),char(13),char(0),char(-105),char(0),char(13),char(0),char(-104),char(0),char(13),char(0),char(-110),char(0),char(13),char(0),char(-103),char(0), +char(13),char(0),char(-102),char(0),char(13),char(0),char(-101),char(0),char(13),char(0),char(-100),char(0),char(7),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0), +char(7),char(0),char(-97),char(0),char(7),char(0),char(-96),char(0),char(7),char(0),char(-95),char(0),char(7),char(0),char(-94),char(0),char(7),char(0),char(-93),char(0), +char(7),char(0),char(-92),char(0),char(7),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(56),char(0),char(22),char(0),char(49),char(0),char(-109),char(0), +char(18),char(0),char(-108),char(0),char(14),char(0),char(-107),char(0),char(14),char(0),char(-106),char(0),char(14),char(0),char(-105),char(0),char(14),char(0),char(-104),char(0), +char(14),char(0),char(-110),char(0),char(14),char(0),char(-103),char(0),char(14),char(0),char(-102),char(0),char(14),char(0),char(-101),char(0),char(14),char(0),char(-100),char(0), +char(8),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(8),char(0),char(-97),char(0),char(8),char(0),char(-96),char(0),char(8),char(0),char(-95),char(0), +char(8),char(0),char(-94),char(0),char(8),char(0),char(-93),char(0),char(8),char(0),char(-92),char(0),char(8),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0), +char(0),char(0),char(37),char(0),char(57),char(0),char(2),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(58),char(0),char(13),char(0), +char(55),char(0),char(-87),char(0),char(55),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0), +char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0), +char(4),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(59),char(0),char(13),char(0),char(60),char(0),char(-87),char(0), +char(60),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0), +char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0), +char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(61),char(0),char(14),char(0),char(56),char(0),char(-87),char(0),char(56),char(0),char(-86),char(0), +char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0), +char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0), +char(4),char(0),char(-76),char(0),char(0),char(0),char(-75),char(0),char(62),char(0),char(3),char(0),char(59),char(0),char(-74),char(0),char(13),char(0),char(-73),char(0), +char(13),char(0),char(-72),char(0),char(63),char(0),char(3),char(0),char(61),char(0),char(-74),char(0),char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0), +char(64),char(0),char(3),char(0),char(59),char(0),char(-74),char(0),char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(65),char(0),char(13),char(0), +char(59),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0), +char(4),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),char(7),char(0),char(-63),char(0), +char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(66),char(0),char(13),char(0),char(59),char(0),char(-74),char(0), +char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0), +char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0), +char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(67),char(0),char(14),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0), +char(20),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0), +char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0), +char(8),char(0),char(-60),char(0),char(0),char(0),char(-59),char(0),char(68),char(0),char(10),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0), +char(20),char(0),char(-70),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-62),char(0), +char(8),char(0),char(-61),char(0),char(8),char(0),char(-60),char(0),char(8),char(0),char(127),char(0),char(69),char(0),char(11),char(0),char(59),char(0),char(-74),char(0), +char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0), +char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(127),char(0),char(0),char(0),char(21),char(0), +char(70),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0), +char(13),char(0),char(-54),char(0),char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0), +char(71),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(14),char(0),char(-55),char(0), +char(14),char(0),char(-54),char(0),char(14),char(0),char(-53),char(0),char(14),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0), +char(72),char(0),char(5),char(0),char(70),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(7),char(0),char(-46),char(0), +char(7),char(0),char(-45),char(0),char(73),char(0),char(5),char(0),char(71),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),char(8),char(0),char(-47),char(0), +char(8),char(0),char(-46),char(0),char(8),char(0),char(-45),char(0),char(74),char(0),char(41),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0), +char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0), +char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(13),char(0),char(-40),char(0),char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0), +char(13),char(0),char(-37),char(0),char(13),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),char(13),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0), +char(0),char(0),char(-32),char(0),char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0),char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0), +char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),char(13),char(0),char(-28),char(0),char(13),char(0),char(-27),char(0),char(13),char(0),char(-26),char(0), +char(13),char(0),char(-25),char(0),char(13),char(0),char(-24),char(0),char(13),char(0),char(-23),char(0),char(13),char(0),char(-22),char(0),char(13),char(0),char(-21),char(0), +char(13),char(0),char(-20),char(0),char(13),char(0),char(-19),char(0),char(13),char(0),char(-18),char(0),char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0), +char(0),char(0),char(-15),char(0),char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),char(75),char(0),char(41),char(0), +char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0), +char(14),char(0),char(-44),char(0),char(14),char(0),char(-43),char(0),char(14),char(0),char(-42),char(0),char(14),char(0),char(-41),char(0),char(14),char(0),char(-40),char(0), +char(14),char(0),char(-39),char(0),char(14),char(0),char(-38),char(0),char(14),char(0),char(-37),char(0),char(14),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0), +char(14),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(0),char(0),char(-32),char(0),char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0), +char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0),char(14),char(0),char(-53),char(0),char(14),char(0),char(-52),char(0),char(14),char(0),char(-28),char(0), +char(14),char(0),char(-27),char(0),char(14),char(0),char(-26),char(0),char(14),char(0),char(-25),char(0),char(14),char(0),char(-24),char(0),char(14),char(0),char(-23),char(0), +char(14),char(0),char(-22),char(0),char(14),char(0),char(-21),char(0),char(14),char(0),char(-20),char(0),char(14),char(0),char(-19),char(0),char(14),char(0),char(-18),char(0), +char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0),char(0),char(0),char(-15),char(0),char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0), +char(4),char(0),char(-12),char(0),char(76),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0), +char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0), +char(4),char(0),char(-50),char(0),char(77),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0), +char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0), +char(4),char(0),char(-50),char(0),char(78),char(0),char(5),char(0),char(58),char(0),char(-74),char(0),char(13),char(0),char(-11),char(0),char(13),char(0),char(-10),char(0), +char(7),char(0),char(-9),char(0),char(0),char(0),char(37),char(0),char(79),char(0),char(4),char(0),char(61),char(0),char(-74),char(0),char(14),char(0),char(-11),char(0), +char(14),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),char(80),char(0),char(4),char(0),char(7),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0), +char(7),char(0),char(-6),char(0),char(4),char(0),char(79),char(0),char(81),char(0),char(10),char(0),char(80),char(0),char(-5),char(0),char(13),char(0),char(-4),char(0), +char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(7),char(0),char(-99),char(0), +char(7),char(0),char(1),char(1),char(4),char(0),char(2),char(1),char(4),char(0),char(53),char(0),char(82),char(0),char(4),char(0),char(80),char(0),char(-5),char(0), +char(4),char(0),char(3),char(1),char(7),char(0),char(4),char(1),char(4),char(0),char(5),char(1),char(83),char(0),char(4),char(0),char(13),char(0),char(0),char(1), +char(80),char(0),char(-5),char(0),char(4),char(0),char(6),char(1),char(7),char(0),char(7),char(1),char(84),char(0),char(7),char(0),char(13),char(0),char(8),char(1), +char(80),char(0),char(-5),char(0),char(4),char(0),char(9),char(1),char(7),char(0),char(10),char(1),char(7),char(0),char(11),char(1),char(7),char(0),char(12),char(1), +char(4),char(0),char(53),char(0),char(85),char(0),char(6),char(0),char(17),char(0),char(13),char(1),char(13),char(0),char(11),char(1),char(13),char(0),char(14),char(1), +char(60),char(0),char(15),char(1),char(4),char(0),char(16),char(1),char(7),char(0),char(12),char(1),char(86),char(0),char(26),char(0),char(4),char(0),char(17),char(1), +char(7),char(0),char(18),char(1),char(7),char(0),char(127),char(0),char(7),char(0),char(19),char(1),char(7),char(0),char(20),char(1),char(7),char(0),char(21),char(1), +char(7),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(7),char(0),char(25),char(1),char(7),char(0),char(26),char(1), +char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1), +char(7),char(0),char(32),char(1),char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(7),char(0),char(35),char(1),char(7),char(0),char(36),char(1), +char(4),char(0),char(37),char(1),char(4),char(0),char(38),char(1),char(4),char(0),char(39),char(1),char(4),char(0),char(40),char(1),char(4),char(0),char(120),char(0), +char(87),char(0),char(12),char(0),char(17),char(0),char(41),char(1),char(17),char(0),char(42),char(1),char(17),char(0),char(43),char(1),char(13),char(0),char(44),char(1), +char(13),char(0),char(45),char(1),char(7),char(0),char(46),char(1),char(4),char(0),char(47),char(1),char(4),char(0),char(48),char(1),char(4),char(0),char(49),char(1), +char(4),char(0),char(50),char(1),char(7),char(0),char(10),char(1),char(4),char(0),char(53),char(0),char(88),char(0),char(27),char(0),char(19),char(0),char(51),char(1), +char(17),char(0),char(52),char(1),char(17),char(0),char(53),char(1),char(13),char(0),char(44),char(1),char(13),char(0),char(54),char(1),char(13),char(0),char(55),char(1), +char(13),char(0),char(56),char(1),char(13),char(0),char(57),char(1),char(13),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(7),char(0),char(60),char(1), +char(4),char(0),char(61),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1), +char(4),char(0),char(66),char(1),char(4),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1), +char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(4),char(0),char(74),char(1),char(4),char(0),char(75),char(1), +char(4),char(0),char(76),char(1),char(89),char(0),char(12),char(0),char(9),char(0),char(77),char(1),char(9),char(0),char(78),char(1),char(13),char(0),char(79),char(1), +char(7),char(0),char(80),char(1),char(7),char(0),char(-125),char(0),char(7),char(0),char(81),char(1),char(4),char(0),char(82),char(1),char(13),char(0),char(83),char(1), +char(4),char(0),char(84),char(1),char(4),char(0),char(85),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(19),char(0), +char(50),char(0),char(-109),char(0),char(87),char(0),char(87),char(1),char(80),char(0),char(88),char(1),char(81),char(0),char(89),char(1),char(82),char(0),char(90),char(1), +char(83),char(0),char(91),char(1),char(84),char(0),char(92),char(1),char(85),char(0),char(93),char(1),char(88),char(0),char(94),char(1),char(89),char(0),char(95),char(1), +char(4),char(0),char(96),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(97),char(1),char(4),char(0),char(98),char(1),char(4),char(0),char(99),char(1), +char(4),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(86),char(0),char(103),char(1),char(91),char(0),char(20),char(0), +char(16),char(0),char(104),char(1),char(14),char(0),char(105),char(1),char(14),char(0),char(106),char(1),char(14),char(0),char(107),char(1),char(14),char(0),char(108),char(1), +char(14),char(0),char(109),char(1),char(8),char(0),char(110),char(1),char(4),char(0),char(111),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(112),char(1), +char(4),char(0),char(113),char(1),char(8),char(0),char(114),char(1),char(8),char(0),char(115),char(1),char(8),char(0),char(116),char(1),char(8),char(0),char(117),char(1), +char(8),char(0),char(118),char(1),char(0),char(0),char(119),char(1),char(0),char(0),char(120),char(1),char(49),char(0),char(121),char(1),char(0),char(0),char(122),char(1), +char(92),char(0),char(20),char(0),char(15),char(0),char(104),char(1),char(13),char(0),char(105),char(1),char(13),char(0),char(106),char(1),char(13),char(0),char(107),char(1), +char(13),char(0),char(108),char(1),char(13),char(0),char(109),char(1),char(4),char(0),char(112),char(1),char(7),char(0),char(110),char(1),char(4),char(0),char(111),char(1), +char(4),char(0),char(86),char(1),char(7),char(0),char(114),char(1),char(7),char(0),char(115),char(1),char(7),char(0),char(116),char(1),char(4),char(0),char(113),char(1), +char(7),char(0),char(117),char(1),char(7),char(0),char(118),char(1),char(0),char(0),char(119),char(1),char(0),char(0),char(120),char(1),char(50),char(0),char(121),char(1), +char(0),char(0),char(122),char(1),char(93),char(0),char(9),char(0),char(20),char(0),char(123),char(1),char(14),char(0),char(124),char(1),char(8),char(0),char(125),char(1), +char(0),char(0),char(126),char(1),char(91),char(0),char(90),char(1),char(49),char(0),char(127),char(1),char(0),char(0),char(122),char(1),char(4),char(0),char(97),char(1), +char(0),char(0),char(37),char(0),char(94),char(0),char(7),char(0),char(0),char(0),char(126),char(1),char(92),char(0),char(90),char(1),char(50),char(0),char(127),char(1), +char(19),char(0),char(123),char(1),char(13),char(0),char(124),char(1),char(7),char(0),char(125),char(1),char(4),char(0),char(97),char(1),}; int sBulletDNAlen64= sizeof(sBulletDNAstr64); diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.h b/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.h index 033895b1e5..9d95e1c8ab 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btSerializer.h @@ -391,7 +391,8 @@ class btDefaultSerializer : public btSerializer btDefaultSerializer(int totalSize=0, unsigned char* buffer=0) - :m_totalSize(totalSize), + :m_uniqueIdGenerator(0), + m_totalSize(totalSize), m_currentSize(0), m_dna(0), m_dnaLength(0), @@ -446,6 +447,26 @@ class btDefaultSerializer : public btSerializer btAlignedFree(m_dna); } + static int getMemoryDnaSizeInBytes() + { + const bool VOID_IS_8 = ((sizeof(void*) == 8)); + + if (VOID_IS_8) + { + return sBulletDNAlen64; + } + return sBulletDNAlen; + } + static const char* getMemoryDna() + { + const bool VOID_IS_8 = ((sizeof(void*) == 8)); + if (VOID_IS_8) + { + return (const char*)sBulletDNAstr64; + } + return (const char*)sBulletDNAstr; + } + void insertHeader() { writeHeader(m_buffer); @@ -484,7 +505,7 @@ class btDefaultSerializer : public btSerializer buffer[9] = '2'; buffer[10] = '8'; - buffer[11] = '4'; + buffer[11] = '6'; } @@ -541,6 +562,7 @@ class btDefaultSerializer : public btSerializer virtual void* getUniquePointer(void*oldPtr) { + btAssert(m_uniqueIdGenerator >= 0); if (!oldPtr) return 0; diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btThreads.cpp b/Source/ThirdParty/Bullet/src/LinearMath/btThreads.cpp new file mode 100644 index 0000000000..b72301a2e2 --- /dev/null +++ b/Source/ThirdParty/Bullet/src/LinearMath/btThreads.cpp @@ -0,0 +1,231 @@ +/* +Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.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. +*/ + + +#include "btThreads.h" + +// +// Lightweight spin-mutex based on atomics +// Using ordinary system-provided mutexes like Windows critical sections was noticeably slower +// presumably because when it fails to lock at first it would sleep the thread and trigger costly +// context switching. +// + +#if BT_THREADSAFE + +#if __cplusplus >= 201103L + +// for anything claiming full C++11 compliance, use C++11 atomics +// on GCC or Clang you need to compile with -std=c++11 +#define USE_CPP11_ATOMICS 1 + +#elif defined( _MSC_VER ) + +// on MSVC, use intrinsics instead +#define USE_MSVC_INTRINSICS 1 + +#elif defined( __GNUC__ ) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) + +// available since GCC 4.7 and some versions of clang +// todo: check for clang +#define USE_GCC_BUILTIN_ATOMICS 1 + +#elif defined( __GNUC__ ) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) + +// available since GCC 4.1 +#define USE_GCC_BUILTIN_ATOMICS_OLD 1 + +#endif + + +#if USE_CPP11_ATOMICS + +#include +#include + +#define THREAD_LOCAL_STATIC thread_local static + +bool btSpinMutex::tryLock() +{ + std::atomic* aDest = reinterpret_cast*>(&mLock); + int expected = 0; + return std::atomic_compare_exchange_weak_explicit( aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire ); +} + +void btSpinMutex::lock() +{ + // note: this lock does not sleep the thread. + while (! tryLock()) + { + // spin + } +} + +void btSpinMutex::unlock() +{ + std::atomic* aDest = reinterpret_cast*>(&mLock); + std::atomic_store_explicit( aDest, int(0), std::memory_order_release ); +} + + +#elif USE_MSVC_INTRINSICS + +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#define THREAD_LOCAL_STATIC __declspec( thread ) static + + +bool btSpinMutex::tryLock() +{ + volatile long* aDest = reinterpret_cast(&mLock); + return ( 0 == _InterlockedCompareExchange( aDest, 1, 0) ); +} + +void btSpinMutex::lock() +{ + // note: this lock does not sleep the thread + while (! tryLock()) + { + // spin + } +} + +void btSpinMutex::unlock() +{ + volatile long* aDest = reinterpret_cast( &mLock ); + _InterlockedExchange( aDest, 0 ); +} + +#elif USE_GCC_BUILTIN_ATOMICS + +#define THREAD_LOCAL_STATIC static __thread + + +bool btSpinMutex::tryLock() +{ + int expected = 0; + bool weak = false; + const int memOrderSuccess = __ATOMIC_ACQ_REL; + const int memOrderFail = __ATOMIC_ACQUIRE; + return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail); +} + +void btSpinMutex::lock() +{ + // note: this lock does not sleep the thread + while (! tryLock()) + { + // spin + } +} + +void btSpinMutex::unlock() +{ + __atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE); +} + +#elif USE_GCC_BUILTIN_ATOMICS_OLD + + +#define THREAD_LOCAL_STATIC static __thread + +bool btSpinMutex::tryLock() +{ + return __sync_bool_compare_and_swap(&mLock, int(0), int(1)); +} + +void btSpinMutex::lock() +{ + // note: this lock does not sleep the thread + while (! tryLock()) + { + // spin + } +} + +void btSpinMutex::unlock() +{ + // write 0 + __sync_fetch_and_and(&mLock, int(0)); +} + +#else //#elif USE_MSVC_INTRINSICS + +#error "no threading primitives defined -- unknown platform" + +#endif //#else //#elif USE_MSVC_INTRINSICS + + +struct ThreadsafeCounter +{ + unsigned int mCounter; + btSpinMutex mMutex; + + ThreadsafeCounter() {mCounter=0;} + + unsigned int getNext() + { + // no need to optimize this with atomics, it is only called ONCE per thread! + mMutex.lock(); + unsigned int val = mCounter++; + mMutex.unlock(); + return val; + } +}; + +static ThreadsafeCounter gThreadCounter; + + +// return a unique index per thread, starting with 0 and counting up +unsigned int btGetCurrentThreadIndex() +{ + const unsigned int kNullIndex = ~0U; + THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex; + if ( sThreadIndex == kNullIndex ) + { + sThreadIndex = gThreadCounter.getNext(); + } + return sThreadIndex; +} + +bool btIsMainThread() +{ + return btGetCurrentThreadIndex() == 0; +} + +#else // #if BT_THREADSAFE + +// These should not be called ever +void btSpinMutex::lock() +{ + btAssert(!"unimplemented btSpinMutex::lock() called"); +} + +void btSpinMutex::unlock() +{ + btAssert(!"unimplemented btSpinMutex::unlock() called"); +} + +bool btSpinMutex::tryLock() +{ + btAssert(!"unimplemented btSpinMutex::tryLock() called"); + return true; +} + + +#endif // #if BT_THREADSAFE + diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btThreads.h b/Source/ThirdParty/Bullet/src/LinearMath/btThreads.h new file mode 100644 index 0000000000..a15e5250bd --- /dev/null +++ b/Source/ThirdParty/Bullet/src/LinearMath/btThreads.h @@ -0,0 +1,75 @@ +/* +Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.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 BT_THREADS_H +#define BT_THREADS_H + +#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE + +/// +/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts +/// a thread to sleep because it is designed to be used with a task scheduler +/// which has one thread per core and the threads don't sleep until they +/// run out of tasks. Not good for general purpose use. +/// +class btSpinMutex +{ + int mLock; + +public: + btSpinMutex() + { + mLock = 0; + } + void lock(); + void unlock(); + bool tryLock(); +}; + +#if BT_THREADSAFE + +// for internal Bullet use only +SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* mutex ) +{ + mutex->lock(); +} + +SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* mutex ) +{ + mutex->unlock(); +} + +SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* mutex ) +{ + return mutex->tryLock(); +} + +// for internal use only +bool btIsMainThread(); +unsigned int btGetCurrentThreadIndex(); +const unsigned int BT_MAX_THREAD_COUNT = 64; + +#else + +// for internal Bullet use only +// if BT_THREADSAFE is undefined or 0, should optimize away to nothing +SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* ) {} +SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* ) {} +SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* ) {return true;} +#endif + + +#endif //BT_THREADS_H diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btTransform.h b/Source/ThirdParty/Bullet/src/LinearMath/btTransform.h index 907627379b..d4f939a5d9 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btTransform.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btTransform.h @@ -127,7 +127,7 @@ ATTRIBUTE_ALIGNED16(class) btTransform { /**@brief Set from an array - * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ + * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */ void setFromOpenGLMatrix(const btScalar *m) { m_basis.setFromOpenGLSubMatrix(m); @@ -135,7 +135,7 @@ ATTRIBUTE_ALIGNED16(class) btTransform { } /**@brief Fill an array representation - * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ + * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */ void getOpenGLMatrix(btScalar *m) const { m_basis.getOpenGLSubMatrix(m); diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btVector3.cpp b/Source/ThirdParty/Bullet/src/LinearMath/btVector3.cpp index 4f46ff55d6..3c9b60a74c 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btVector3.cpp +++ b/Source/ThirdParty/Bullet/src/LinearMath/btVector3.cpp @@ -59,7 +59,7 @@ long _maxdot_large( const float *vv, const float *vec, unsigned long count, floa float4 vvec = _mm_loadu_ps( vec ); float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy - + long maxIndex = -1L; size_t segment = 0; diff --git a/Source/ThirdParty/Bullet/src/LinearMath/btVector3.h b/Source/ThirdParty/Bullet/src/LinearMath/btVector3.h index c118ec0e41..4986319691 100644 --- a/Source/ThirdParty/Bullet/src/LinearMath/btVector3.h +++ b/Source/ThirdParty/Bullet/src/LinearMath/btVector3.h @@ -14,6 +14,7 @@ subject to the following restrictions: // Modified by Yao Wei Tjong for Urho3D + #ifndef BT_VECTOR3_H #define BT_VECTOR3_H @@ -267,10 +268,20 @@ ATTRIBUTE_ALIGNED16(class) btVector3 /**@brief Return the norm (length) of the vector */ SIMD_FORCE_INLINE btScalar norm() const - { + { return length(); } + /**@brief Return the norm (length) of the vector */ + SIMD_FORCE_INLINE btScalar safeNorm() const + { + btScalar d = length2(); + //workaround for some clang/gcc issue of sqrtf(tiny number) = -INF + if (d>SIMD_EPSILON) + return btSqrt(d); + return btScalar(0); + } + /**@brief Return the distance squared between the ends of this and another vector * This is symantically treating the vector like a point */ SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; @@ -281,14 +292,16 @@ ATTRIBUTE_ALIGNED16(class) btVector3 SIMD_FORCE_INLINE btVector3& safeNormalize() { - btVector3 absVec = this->absolute(); - int maxIndex = absVec.maxAxis(); - if (absVec[maxIndex]>0) + btScalar l2 = length2(); + //triNormal.normalize(); + if (l2 >= SIMD_EPSILON*SIMD_EPSILON) + { + (*this) /= btSqrt(l2); + } + else { - *this /= absVec[maxIndex]; - return *this /= length(); + setValue(1, 0, 0); } - setValue(1,0,0); return *this; } @@ -1004,7 +1017,7 @@ SIMD_FORCE_INLINE long btVector3::maxDot( const btVector3 *array, long arra #ifdef BT_USE_SSE // Urho3D - to be consistent with the function return below const long scalar_cutoff = 10; long _maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut ); - #elif BT_USE_NEON + #elif defined BT_USE_NEON const long scalar_cutoff = 4; extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut ); #endif diff --git a/Source/ThirdParty/Bullet/src/btBulletCollisionCommon.h b/Source/ThirdParty/Bullet/src/btBulletCollisionCommon.h index af981b5d36..948e02eb4c 100644 --- a/Source/ThirdParty/Bullet/src/btBulletCollisionCommon.h +++ b/Source/ThirdParty/Bullet/src/btBulletCollisionCommon.h @@ -52,7 +52,6 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" -#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" #include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" ///Math library & Utils diff --git a/Source/ThirdParty/Civetweb/CMakeLists.txt b/Source/ThirdParty/Civetweb/CMakeLists.txt index 8b7e7b7347..ede6e42aa0 100644 --- a/Source/ThirdParty/Civetweb/CMakeLists.txt +++ b/Source/ThirdParty/Civetweb/CMakeLists.txt @@ -24,6 +24,8 @@ set (TARGET_NAME Civetweb) # Define preprocessor macros +# Always disable Common Gateway Interface +add_definitions (-DNO_CGI) if (WIN32) include (CheckStructHasMember) check_struct_has_member (struct\ timespec tv_sec time.h HAVE_STRUCT_TIMESPEC_TV_SEC) @@ -34,10 +36,10 @@ if (WIN32) add_definitions (-D_TIMESPEC_DEFINED) endif () endif () -elseif (APPLE) - if (CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.12 AND IPHONEOS_DEPLOYMENT_TARGET VERSION_LESS 10.0 AND APPLETVOS_DEPLOYMENT_TARGET VERSION_LESS 10.0) - add_definitions (-D_DARWIN_FEATURE_CLOCK_GETTIME=0) - else () +elseif (APPLE AND (NOT IOS OR IPHONEOS_DEPLOYMENT_TARGET STREQUAL "" OR NOT IPHONEOS_DEPLOYMENT_TARGET VERSION_LESS 10.0)) # We cheat a little bit here with a hard-coded check because iOS 10.3 SDK when targeting 9.3 has strong symbol for iPhoneOS archs but weak symbol for iPhoneSimulator archs + include (CheckLibraryExists) + check_library_exists (c clock_gettime "" FOUND_CLOCK_GETTIME_IN_C) + if (FOUND_CLOCK_GETTIME_IN_C) add_definitions (-DHAVE_CLOCK_GETTIME) endif () endif () diff --git a/Source/ThirdParty/FreeType/README b/Source/ThirdParty/FreeType/README index 097024c6e9..926e9dc117 100644 --- a/Source/ThirdParty/FreeType/README +++ b/Source/ThirdParty/FreeType/README @@ -1,5 +1,5 @@ - FreeType 2.7.1 - ============== + FreeType 2.8 + ============ Homepage: http://www.freetype.org @@ -24,9 +24,9 @@ and download one of the following files. - freetype-doc-2.7.1.tar.bz2 - freetype-doc-2.7.1.tar.gz - ftdoc271.zip + freetype-doc-2.8.tar.bz2 + freetype-doc-2.8.tar.gz + ftdoc28.zip To view the documentation online, go to @@ -71,7 +71,7 @@ ---------------------------------------------------------------------- -Copyright 2006-2016 by +Copyright 2006-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/CHANGES b/Source/ThirdParty/FreeType/docs/CHANGES index dccdb6e28b..3ee9510d07 100644 --- a/Source/ThirdParty/FreeType/docs/CHANGES +++ b/Source/ThirdParty/FreeType/docs/CHANGES @@ -1,4 +1,111 @@ +CHANGES BETWEEN 2.7.1 and 2.8 + + I. IMPORTANT CHANGES + + - Support for OpenType Variation Fonts is now complete. The last + missing part was handling the `VVAR' and `MVAR' tables, which is + available with this release. + + - A new function `FT_Face_Properties' allows the control of some + module and library properties per font. Currently, the + following properties can be handled: stem darkening, LCD filter + weights, and the random seed for the `random' CFF operator. + + - The PCF change to show more `colourful' family names (introduced + in version 2.7.1) was too radical; it can now be configured with + PCF_CONFIG_OPTION_LONG_FAMILY_NAMES at compile time. If + activated, it can be switched off at run time with the new pcf + property `no-long-family-names'. If the `FREETYPE_PROPERTIES' + environment variable is available, you can say + + FREETYPE_PROPERTIES=pcf:no-long-family-names=1 + + - Support for the following scripts has been added to the + auto-hinter. + + Adlam, Avestan, Bamum, Buhid, Carian, Chakma, Coptic, Cypriot, + Deseret, Glagolitic, Gothic, Kayah, Lisu, N'Ko, Ol Chiki, Old + Turkic, Osage, Osmanya, Saurashtra, Shavian, Sundanese, Tai + Viet, Tifinagh, Unified Canadian Syllabics, Vai + + + II. IMPORTANT BUG FIXES + + - `Light' auto-hinting mode no longer uses TrueType metrics for + TrueType fonts. This bug was introduced in version 2.4.6, + causing horizontal scaling also. Almost all GNU/Linux + distributions (with Fedora as a notable exception) disabled the + corresponding patch for good reasons; chances are thus high that + you won't notice a difference. + + If optical backward compatibility for legacy applications is + necessary, you might enable the AF_CONFIG_OPTION_TT_SIZE_METRICS + configuration option. However, it is strongly recommended to + avoid that, adjusting font sizes instead. + + - If a TrueType font gets loaded with FT_LOAD_NO_HINTING, FreeType + now scales the font linearly again (bug introduced in version + 2.4.6). + + - CVE-2017-8105, CVE-2017-8287: Older FreeType versions have + out-of-bounds writes caused by heap-based buffer overflows + related to Type 1 fonts. + + https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8105 + https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8287 + + + III. MISCELLANEOUS + + - A new function `FT_Set_Default_Properties' has been added to + parse the `FREETYPE_PROPERTIES' environment variable + (previously, it was internal only). `FT_Init_FreeType' always + call this function, but `FT_New_Library' does not (similar to + `FT_Add_Default_Modules'). + + - To be in sync with OpenType version 1.7 and newer, macros + + FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY, + FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY, + TT_NAME_ID_PREFERRED_FAMILY + TT_NAME_ID_PREFERRED_SUBFAMILY + + are renamed to + + FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY, + FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY, + TT_NAME_ID_TYPOGRAPHIC_FAMILY + TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY + + The old macro names are deprecated (but still available). + + - Support for SFNT `name' tables has been improved. + + . Format 1 `name' tables are now supported. Use new function + `FT_Get_Sfnt_LangTag' to access associated language tags. + + . Language, encoding, and name IDs have been updated to OpenType + version 1.8.1. + + - The new CFF engine now handles the `random' operator. All CFF + opcodes are now supported. + + - The CFF module has a new property `random-seed' to control the + pseudo-random number generation for the `random' operator. + + - The `freetype-config' script is now a wrapper of `pkg-config' if + this program is available in the path. + + - FT_LOAD_TARGET_LCD is now a variant of FT_LOAD_TARGET_LIGHT; + this should provide better rendering results. + + - A mode to display light auto-hinting with sub-pixel positioning + has been added to `ftdiff'. + + +====================================================================== + CHANGES BETWEEN 2.7 and 2.7.1 I. IMPORTANT CHANGES @@ -18,6 +125,12 @@ CHANGES BETWEEN 2.7 and 2.7.1 - Handling of raw CID fonts was partially broken (bug introduced in 2.6.4). + - CVE-2016-10328: Older FreeType versions had an out-of-bounds + write caused by a heap-based buffer overflow related to the CFF + fonts. + + http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10328 + III. MISCELLANEOUS @@ -195,7 +308,7 @@ CHANGES BETWEEN 2.6.3 and 2.6.4 - Type 42 fonts as created by LilyPond are now supported. - - Minor rendering improvments in the auto-hinter. + - Minor rendering improvements in the auto-hinter. - For experimental reasons, the old CFF engine now supports all CFF operators except `random', including the deprecated Multiple @@ -240,7 +353,7 @@ CHANGES BETWEEN 2.6.2 and 2.6.3 to the user. The exception to this is `__FTERRORS_H__', which must be sometimes undefined by the user to get FreeType error strings: Both this form and the new `FTERRORS_H_' macro are - accepted for backwards compatibility. + accepted for backward compatibility. - Minor improvements mainly to the Type 1 driver. @@ -481,17 +594,17 @@ CHANGES BETWEEN 2.5.5 and 2.6 compiler warnings. - Function `FT_Bitmap_New' has been renamed to `FT_Bitmap_Init', - since this name better reflects its function. For backwards + since this name better reflects its function. For backward compatibility, the old function name is still available. - Function `FT_Get_X11_Font_Format' has been renamed to `FT_Get_Font_Format', since this name better reflects its - function. For backwards compatibility, the old function name is + function. For backward compatibility, the old function name is still available. Additionally, the header file macro for this function has been renamed to `FT_FONT_FORMATS_H' (the old name `FT_XFREE86_H' is - retained for backwards compatibility). + retained for backward compatibility). - Various improvements to the `ftgrid' demo program. @@ -925,7 +1038,7 @@ index ebcf189..3f2ce6b 100644 II. MISCELLANEOUS - The (top-level) `configure' script now respects the MAKE - environment variable to specify a `make' binary. For backwards + environment variable to specify a `make' binary. For backward compatibility, GNUMAKE still overrides MAKE, though. - The `ftview' and `ftdiff' demo programs have been redesigned, @@ -2144,7 +2257,7 @@ CHANGES BETWEEN 2.1.10 and 2.1.9 probably using a different pitch, and to further manipulate it. - A new API `FT_Outline_Embolden' (in FT_OUTLINE_H) gives finer - control how outlines are embolded. + control how outlines are emboldened. - `FT_GlyphSlot_Embolden' (in FT_SYNTHESIS_H) now handles bitmaps also (code contributed by Chia I Wu). Note that this function @@ -2263,7 +2376,7 @@ CHANGES BETWEEN 2.1.8 and 2.1.7 correctly treated as a CID, similar to FreeType's CID driver module. Note that CID CMap support is still missing. - - The FT_FACE_FLAGS_GLYPH_NAMES flag is now set correctly for all + - The FT_FACE_FLAG_GLYPH_NAMES flag is now set correctly for all font formats. - Some subsetted Type 1 fonts weren't parsed correctly. This bug @@ -2554,7 +2667,7 @@ CHANGES BETWEEN 2.1.5 and 2.1.4 - FT_ENCODING_MS_{SJIS,GB2312,BIG5,WANSUNG,JOHAB} are now deprecated in favour of - FT_ENCODING_{SJIS,GB2312,GIB5,WANSONG,JOHAB} -- those encodings + FT_ENCODING_{SJIS,GB2312,BIG5,WANSUNG,JOHAB} -- those encodings are not specific to Microsoft. @@ -4676,7 +4789,7 @@ Extensions support: ------------------------------------------------------------------------ -Copyright 2000-2016 by +Copyright 2000-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/CUSTOMIZE b/Source/ThirdParty/FreeType/docs/CUSTOMIZE index e8817b72b6..6d1587e097 100644 --- a/Source/ThirdParty/FreeType/docs/CUSTOMIZE +++ b/Source/ThirdParty/FreeType/docs/CUSTOMIZE @@ -139,7 +139,7 @@ IV. Overriding default configuration and module headers ---------------------------------------------------------------------- -Copyright 2003-2016 by +Copyright 2003-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/DEBUG b/Source/ThirdParty/FreeType/docs/DEBUG index 29e10721cf..e5e9390c79 100644 --- a/Source/ThirdParty/FreeType/docs/DEBUG +++ b/Source/ThirdParty/FreeType/docs/DEBUG @@ -6,7 +6,7 @@ I. Configuration macros There are several ways to enable debugging features in a FreeType 2 builds. This is controlled through the definition of special macros -located in the file `ftoptions.h'. The macros are: +located in the file `ftoption.h'. The macros are: FT_DEBUG_LEVEL_ERROR @@ -191,7 +191,7 @@ behaviour of FreeType at runtime. ------------------------------------------------------------------------ -Copyright 2002-2016 by +Copyright 2002-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/INSTALL b/Source/ThirdParty/FreeType/docs/INSTALL index 5155a4b2ec..d6ec0d83b1 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL +++ b/Source/ThirdParty/FreeType/docs/INSTALL @@ -16,6 +16,8 @@ I. Normal installation and upgrades GNU Make VERSION 3.80 OR NEWER IS NEEDED! + [For `cmake' see below.] + 2. On VMS with the `mms' build tool @@ -75,7 +77,7 @@ II. Custom builds of the library ---------------------------------------------------------------------- -Copyright 2000-2016 by +Copyright 2000-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/INSTALL.ANY b/Source/ThirdParty/FreeType/docs/INSTALL.ANY index aae2773087..30b957859d 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL.ANY +++ b/Source/ThirdParty/FreeType/docs/INSTALL.ANY @@ -143,7 +143,7 @@ II. Support for flat-directory compilation ---------------------------------------------------------------------- -Copyright 2003-2016 by +Copyright 2003-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/INSTALL.CROSS b/Source/ThirdParty/FreeType/docs/INSTALL.CROSS index 428580416c..1a837aeeed 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL.CROSS +++ b/Source/ThirdParty/FreeType/docs/INSTALL.CROSS @@ -163,7 +163,7 @@ procedure. ---------------------------------------------------------------------- -Copyright 2006-2016 by +Copyright 2006-2017 by suzuki toshiya, David Turner, Robert Wilhelm, and Werner Lemberg. diff --git a/Source/ThirdParty/FreeType/docs/INSTALL.GNU b/Source/ThirdParty/FreeType/docs/INSTALL.GNU index f1eb0819f5..79b53d8420 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL.GNU +++ b/Source/ThirdParty/FreeType/docs/INSTALL.GNU @@ -148,7 +148,7 @@ instructions in the file `INSTALL.UNIX' instead. ---------------------------------------------------------------------- -Copyright 2003-2016 by +Copyright 2003-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/INSTALL.MAC b/Source/ThirdParty/FreeType/docs/INSTALL.MAC index 42bb0d8637..2587e24a65 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL.MAC +++ b/Source/ThirdParty/FreeType/docs/INSTALL.MAC @@ -1,32 +1,32 @@ -Please follow the instructions in INSTALL.UNIX to install FreeType on +Please follow the instructions in INSTALL.UNIX to install FreeType on Mac OS X. -Currently FreeType2 functions based on some deprecated Carbon APIs -return FT_Err_Unimplemented_Feature always, even if FreeType2 is -configured and built on the system that deprecated Carbon APIs are -available. To enable deprecated FreeType2 functions as far as possible, -replace src/base/ftmac.c by builds/mac/ftmac.c. +Currently FreeType2 functions based on some deprecated Carbon APIs +return `FT_Err_Unimplemented_Feature' always, even if FreeType2 is +configured and built on the system that deprecated Carbon APIs are +available. To enable deprecated FreeType2 functions as far as +possible, replace `src/base/ftmac.c' by `builds/mac/ftmac.c'. -Starting with Mac OS X 10.5, gcc defaults the deployment target -to 10.5. In previous versions of Mac OS X, this defaulted to 10.1. -If you want your built binaries to run only on 10.5, this change -does not concern you. If you want them to also run on older versions -of Mac OS X, then you must either set the MACOSX_DEPLOYMENT_TARGET -environment variable or pass -mmacosx-version-min to gcc. You should -specify the oldest version of Mac OS you want the code to run on. -For example, if you use Bourne shell: +Starting with Mac OS X 10.5, gcc defaults the deployment target to +10.5. In previous versions of Mac OS X, this defaulted to 10.1. If +you want your built binaries to run only on 10.5, this change does not +concern you. If you want them to also run on older versions of Mac +OS X, then you must either set the MACOSX_DEPLOYMENT_TARGET +environment variable or pass `-mmacosx-version-min' to gcc. You +should specify the oldest version of Mac OS you want the code to run +on. For example, if you use Bourne shell: - export MACOSX_DEPLOYMENT_TARGET=10.2 + export MACOSX_DEPLOYMENT_TARGET=10.2 or, if you use C shell: - setenv MACOSX_DEPLOYMENT_TARGET 10.2 + setenv MACOSX_DEPLOYMENT_TARGET 10.2 -Alternatively, you could pass "-mmacosx-version-min=10.2" to gcc. +Alternatively, you could pass `-mmacosx-version-min=10.2' to gcc. -Here the number 10.2 is the lowest version that the built binaries -can run on. In the cases in above, the built binaries will run on -Mac OS X 10.2 and later, but _not_ earlier. If you want to run on -earlier, you have to set lower version, e.g. 10.0. +Here the number 10.2 is the lowest version that the built binaries can +run on. In the above cases, the built binaries will run on Mac OS X +10.2 and later, but _not_ earlier. If you want to run on earlier, you +have to set lower version, e.g., 10.0. For classic Mac OS (Mac OS 7, 8, 9) please refer to builds/mac/README. diff --git a/Source/ThirdParty/FreeType/docs/INSTALL.UNIX b/Source/ThirdParty/FreeType/docs/INSTALL.UNIX index b043883a14..8b620da689 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL.UNIX +++ b/Source/ThirdParty/FreeType/docs/INSTALL.UNIX @@ -28,6 +28,9 @@ or MSys on Win32: As a special exception, 'makepp' can also be used to build FreeType 2. See the file docs/MAKEPP for details. + For builds with `cmake' please check file `CMakeLists.txt'; this + is a contributed file not directly supported by the FreeType team. + 2. Regenerate the configure script if needed -------------------------------------------- @@ -102,7 +105,7 @@ or MSys on Win32: ---------------------------------------------------------------------- -Copyright 2003-2016 by +Copyright 2003-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/INSTALL.VMS b/Source/ThirdParty/FreeType/docs/INSTALL.VMS index ef371d70ba..7a5174d2e6 100644 --- a/Source/ThirdParty/FreeType/docs/INSTALL.VMS +++ b/Source/ThirdParty/FreeType/docs/INSTALL.VMS @@ -49,7 +49,7 @@ V7.2-1. ------------------------------------------------------------------------ -Copyright 2000-2016 by +Copyright 2000-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/TODO b/Source/ThirdParty/FreeType/docs/TODO index 4aa3f09043..c4304b3238 100644 --- a/Source/ThirdParty/FreeType/docs/TODO +++ b/Source/ThirdParty/FreeType/docs/TODO @@ -27,7 +27,7 @@ Other bugs have been registered at the savannah bugzilla of FreeType. ------------------------------------------------------------------------ -Copyright 2001-2016 by +Copyright 2001-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/VERSION.DLL b/Source/ThirdParty/FreeType/docs/VERSION.DLL deleted file mode 100644 index 2d1cc9acff..0000000000 --- a/Source/ThirdParty/FreeType/docs/VERSION.DLL +++ /dev/null @@ -1,123 +0,0 @@ -Due to our use of `libtool' to generate and install the FreeType 2 -libraries on Unix systems, as well as other historical events, it is -generally very difficult to know precisely which release of the font -engine is installed on a given system. - -This file tries to explain why and to document ways to properly detect -FreeType on Unix. - - -1. Version and Release numbers ------------------------------- - -For each new public release of FreeType 2, there are generally *three* -distinct `version' numbers to consider: - - * The official FreeType 2 release number, like 2.3.1 or 2.4.10. - - * The libtool (and Unix) specific version number, like 13.0.7. This - is what `freetype-config --version' returns. - - * The platform-specific shared object number, used for example when - the library is installed as `/usr/lib/libfreetype.so.6.7.1'. - -The platform-specific number is, unsurprisingly, platform-specific and -varies with the operating system you are using (several variants of -Linux, FreeBSD, Solaris, etc.). You should thus _never_ use it, even -for simple tests. - -The libtool-specific number does not equal the release number but is -tied to it. - -The release number is available at *compile* time through the following -macros defined in FT_FREETYPE_H: - - - FREETYPE_MAJOR: major release number - - FREETYPE_MINOR: minor release number - - FREETYPE_PATCH: patch release number - -See below for a small autoconf fragment. - -The release number is also available at *runtime* through the -`FT_Library_Version' API. - - -2. History ----------- - -The following table gives, for all releases since 2.3.0, the -corresponding libtool number, as well as the shared object number found -on _most_ systems, but not all of them: - - - release libtool so - ------------------------------- - 2.5.0 16.2.10 6.10.2 - 2.4.12 16.1.10 6.10.1 - 2.4.11 16.0.10 6.10.0 - 2.4.10 15.0.9 6.9.0 - 2.4.9 14.1.8 6.8.1 - 2.4.8 14.0.8 6.8.0 - 2.4.7 13.2.7 6.7.2 - 2.4.6 13.1.7 6.7.1 - 2.4.5 13.0.7 6.7.0 - 2.4.4 12.2.6 6.6.2 - 2.4.3 12.1.6 6.6.1 - 2.4.2 12.0.6 6.6.0 - 2.4.1 11.1.5 6.5.1 - 2.4.0 11.0.5 6.5.0 - 2.3.12 10.0.4 6.4.0 - 2.3.11 9.22.3 6.3.22 - 2.3.10 9.21.3 6.3.21 - 2.3.9 9.20.3 6.3.20 - 2.3.8 9.19.3 6.3.19 - 2.3.7 9.18.3 6.3.18 - 2.3.6 9.17.3 6.3.17 - 2.3.5 9.16.3 6.3.16 - 2.3.4 9.15.3 6.3.15 - 2.3.3 9.14.3 6.3.14 - 2.3.2 9.13.3 6.3.13 - 2.3.1 9.12.3 6.3.12 - 2.3.0 9.11.3 6.3.11 - - -3. Autoconf Code Fragment -------------------------- - -Lars Clausen contributed the following autoconf fragment to detect which -version of FreeType is installed on a system. This one tests for a -version that is at least 2.0.9; you should change it to check against -other release numbers. - - - AC_MSG_CHECKING([whether FreeType version is 2.0.9 or higher]) - old_CPPFLAGS="$CPPFLAGS" - CPPFLAGS=`freetype-config --cflags` - AC_TRY_CPP([ - -#include -#include FT_FREETYPE_H -#if (FREETYPE_MAJOR*1000 + FREETYPE_MINOR)*1000 + FREETYPE_PATCH < 2000009 -#error Freetype version too low. -#endif - ], - [AC_MSG_RESULT(yes) - FREETYPE_LIBS=`freetype-config --libs` - AC_SUBST(FREETYPE_LIBS) - AC_DEFINE(HAVE_FREETYPE,1,[Define if you have the FreeType2 library]) - CPPFLAGS="$old_CPPFLAGS"], - [AC_MSG_ERROR([Need FreeType library version 2.0.9 or higher])]) - ------------------------------------------------------------------------- - -Copyright 2002-2013 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - ---- end of VERSION.DLL --- diff --git a/Source/ThirdParty/FreeType/docs/VERSIONS.TXT b/Source/ThirdParty/FreeType/docs/VERSIONS.TXT index 82f63a3a6e..e116d34cb5 100644 --- a/Source/ThirdParty/FreeType/docs/VERSIONS.TXT +++ b/Source/ThirdParty/FreeType/docs/VERSIONS.TXT @@ -52,6 +52,7 @@ on _most_ systems, but not all of them: release libtool so ------------------------------- + 2.8.0 20.0.14 6.14.0 2.7.1 19.0.13 6.13.0 2.7.0 18.6.12 6.12.6 2.6.5 18.5.12 6.12.5 @@ -110,7 +111,7 @@ other release numbers. ------------------------------------------------------------------------ -Copyright 2002-2016 by +Copyright 2002-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/formats.txt b/Source/ThirdParty/FreeType/docs/formats.txt index 2181352bdf..1c494f063a 100644 --- a/Source/ThirdParty/FreeType/docs/formats.txt +++ b/Source/ThirdParty/FreeType/docs/formats.txt @@ -7,9 +7,12 @@ Table fields wrapper format The format used to represent the font data. In the table below it is used only if the font format differs. Possible values are - `SFNT' (binary), `PS' (a text header, followed by binary or text - data), `LZW' (compressed with either `gzip' or `compress'), and - `BZ2' (compressed with `bzip2`). + + SFNT binary + PFB binary + PS a text header, followed by binary or text data + LZW compressed with either `gzip' or `compress' + BZ2 compressed with `bzip2'. font format How the font is to be accessed, possibly after converting the file @@ -95,6 +98,9 @@ which isn't supported yet please send a mail too. --- PS TYPE_1 --- type1 T1_SPEC.pdf + (PFA, Type 1 font resource) + PFB PS TYPE_1 --- type1 T1_SPEC.pdf, + 5040.Download_Fonts.pdf (`normal' Type 1 font) --- PS TYPE_1 CID cid PLRM.pdf (CID Font Type 0; Type 9 font) @@ -186,7 +192,7 @@ which isn't supported yet please send a mail too. ------------------------------------------------------------------------ -Copyright 2004-2016 by +Copyright 2004-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, @@ -197,3 +203,7 @@ accept it fully. --- end of formats.txt --- + +Local Variables: +coding: utf-8 +End: diff --git a/Source/ThirdParty/FreeType/docs/freetype-config.1 b/Source/ThirdParty/FreeType/docs/freetype-config.1 new file mode 100644 index 0000000000..eaaa1b95b3 --- /dev/null +++ b/Source/ThirdParty/FreeType/docs/freetype-config.1 @@ -0,0 +1,146 @@ +.TH FREETYPE-CONFIG 1 "May 2017" "FreeType 2.8" +. +. +.SH NAME +. +freetype-config \- Get information about a libfreetype installation +. +. +.SH SYNOPSIS +. +.B freetype-config +.RI [ options ] +. +. +.SH DESCRIPTION +. +.B freetype-config +returns information needed for compiling and linking programs with the +FreeType library, such as linker flags and compilation parameters. +. +Alternatively, it can be used to query information about the +FreeType library version installed on the system, such as the +installation (directory path) prefix or the FreeType version number. +. +.PP +If +.BR pkg-config (1) +is found in the path, +.B freetype-config +acts as a wrapper for +.BR pkg-config . +. +.PP +This program is part of the FreeType package. +. +. +.SH OPTIONS +. +There are two types of options: output/display selection options, and +path override options. +. +. +.SS Output selection options +. +Only one of the output selection options should be given at each program +invocation. +. +.TP +.B \-\-prefix +Return the prefix value of the installed FreeType library (the default +prefix will be `/usr' in most cases for distribution-installed +packages). +. +.TP +.B \-\-exec-prefix +Return the executable prefix value of the installed FreeType library +(will often be the same as the prefix value). +. +.TP +.B \-\-ftversion +Return the FreeType version number, directly derived from file +`freetype.h'. +. +.TP +.B \-\-version +Return the `libtool version' of the FreeType library. +. +.TP +.B \-\-libtool +Return the library name for linking with libtool. +. +.TP +.B \-\-libs +Return compiler flags for linking with the installed FreeType library. +. +.TP +.B \-\-cflags +Return compiler flags for compiling against the installed FreeType library. +. +.TP +.B \-\-static +Make command line options display flags for static linking. +. +.TP +.B \-\-help +Show help and exit. +. +. +.SS Path override options +. +These affect any selected output option, except the libtool version +returned by +.BR \-\-version . +. +.TP +.BI \-\-prefix= PREFIX +Override +.B \-\-prefix +value with +.IR PREFIX . +. +This also sets +.BI \-\-exec-prefix= PREFIX +if option +.B \-\-exec-prefix +is not explicitly given. +. +.TP +.BI \-\-exec-prefix= EPREFIX +Override +.B \-\-exec-prefix +value with +.IR EPREFIX . +. +. +.SH BUGS +In case the libraries FreeType links to are located in non-standard +directories, and +.BR pkg-config (1) +is not available, the output from option +.B \-\-libs +might be incomplete. +. +It is thus recommended to use the +.BR pkg-config (1) +interface instead, which is able to correctly resolve all dependencies. +. +.PP +Setting +.B \-\-exec-prefix +(either explicitly or implicitly) might return incorrect results if +combined with option +.BR \-\-static . +. +The same problem can occur if you set the +.B SYSROOT +environment variable. +. +. +.SH AUTHOR +. +This manual page was contributed by Nis Martensen , +with further refinements from the FreeType team. +. +. +.\" eof diff --git a/Source/ThirdParty/FreeType/docs/raster.txt b/Source/ThirdParty/FreeType/docs/raster.txt index 5e8df51e37..bd3fd00f37 100644 --- a/Source/ThirdParty/FreeType/docs/raster.txt +++ b/Source/ThirdParty/FreeType/docs/raster.txt @@ -618,7 +618,7 @@ II. Rendering Technology ------------------------------------------------------------------------ -Copyright 2003-2016 by +Copyright 2003-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/docs/release b/Source/ThirdParty/FreeType/docs/release index fc03a50b27..f07b067c3a 100644 --- a/Source/ThirdParty/FreeType/docs/release +++ b/Source/ThirdParty/FreeType/docs/release @@ -189,7 +189,7 @@ How to prepare a new release ---------------------------------------------------------------------- -Copyright 2003-2016 by +Copyright 2003-2017 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/Source/ThirdParty/FreeType/include/freetype/config/ftconfig.h b/Source/ThirdParty/FreeType/include/freetype/config/ftconfig.h index 62b807f63e..889aebf5ab 100644 --- a/Source/ThirdParty/FreeType/include/freetype/config/ftconfig.h +++ b/Source/ThirdParty/FreeType/include/freetype/config/ftconfig.h @@ -4,7 +4,7 @@ /* */ /* ANSI-specific configuration file (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -333,6 +333,15 @@ FT_BEGIN_HEADER #endif +#ifdef _WIN64 + /* only 64bit Windows uses the LLP64 data model, i.e., */ + /* 32bit integers, 64bit pointers */ +#define FT_UINT_TO_POINTER( x ) (void*)(unsigned __int64)(x) +#else +#define FT_UINT_TO_POINTER( x ) (void*)(unsigned long)(x) +#endif + + /*************************************************************************/ /* */ /* miscellaneous */ diff --git a/Source/ThirdParty/FreeType/include/freetype/config/ftheader.h b/Source/ThirdParty/FreeType/include/freetype/config/ftheader.h index 68e14834d4..d491af57c3 100644 --- a/Source/ThirdParty/FreeType/include/freetype/config/ftheader.h +++ b/Source/ThirdParty/FreeType/include/freetype/config/ftheader.h @@ -4,7 +4,7 @@ /* */ /* Build macros of the FreeType 2 library. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -354,6 +354,19 @@ #define FT_TRUETYPE_DRIVER_H + /************************************************************************* + * + * @macro: + * FT_PCF_DRIVER_H + * + * @description: + * A macro used in #include statements to name the file containing + * structures and macros related to the PCF driver module. + * + */ +#define FT_PCF_DRIVER_H + + /************************************************************************* * * @macro: diff --git a/Source/ThirdParty/FreeType/include/freetype/config/ftoption.h b/Source/ThirdParty/FreeType/include/freetype/config/ftoption.h index 90c123ef93..1bf6e8f534 100644 --- a/Source/ThirdParty/FreeType/include/freetype/config/ftoption.h +++ b/Source/ThirdParty/FreeType/include/freetype/config/ftoption.h @@ -4,7 +4,7 @@ /* */ /* User-selectable configuration macros (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -82,8 +82,8 @@ FT_BEGIN_HEADER /* to control the various font drivers and modules. The controllable */ /* properties are listed in the section `Controlling FreeType Modules' */ /* in the reference's table of contents; currently there are properties */ - /* for the auto-hinter (file `ftautoh.h'), CFF (file `ftcffdrv.h'), and */ - /* TrueType (file `ftttdrv.h'). */ + /* for the auto-hinter (file `ftautoh.h'), CFF (file `ftcffdrv.h'), */ + /* TrueType (file `ftttdrv.h'), and PCF (file `ftpcfdrv.h'). */ /* */ /* `FREETYPE_PROPERTIES' has the following syntax form (broken here into */ /* multiple lines for better readability). */ @@ -640,17 +640,21 @@ FT_BEGIN_HEADER /* [1] for a technical overview on what this means. See `ttinterp.h' */ /* for more details on the LEAN option. */ /* */ - /* There are three options. */ + /* There are three possible values. */ /* */ - /* 1. This option is associated with the `Infinality' moniker. */ - /* Contributed by an individual nicknamed Infinality with the goal of */ + /* Value 1: */ + /* This value is associated with the `Infinality' moniker, */ + /* contributed by an individual nicknamed Infinality with the goal of */ /* making TrueType fonts render better than on Windows. A high */ /* amount of configurability and flexibility, down to rules for */ /* single glyphs in fonts, but also very slow. Its experimental and */ /* slow nature and the original developer losing interest meant that */ /* this option was never enabled in default builds. */ /* */ - /* 2. The new default mode for the TrueType driver. The Infinality code */ + /* The corresponding interpreter version is v38. */ + /* */ + /* Value 2: */ + /* The new default mode for the TrueType driver. The Infinality code */ /* base was stripped to the bare minimum and all configurability */ /* removed in the name of speed and simplicity. The configurability */ /* was mainly aimed at legacy fonts like Arial, Times New Roman, or */ @@ -660,14 +664,19 @@ FT_BEGIN_HEADER /* that modern and web fonts render well while legacy fonts render */ /* okay. */ /* */ - /* 3. Compile both. */ + /* The corresponding interpreter version is v40. */ + /* */ + /* Value 3: */ + /* Compile both, making both v38 and v40 available (the latter is the */ + /* default). */ /* */ /* By undefining these, you get rendering behavior like on Windows */ /* without ClearType, i.e., Windows XP without ClearType enabled and */ /* Win9x (interpreter version v35). Or not, depending on how much */ /* hinting blood and testing tears the font designer put into a given */ /* font. If you define one or both subpixel hinting options, you can */ - /* switch between between v35 and the ones you define. */ + /* switch between between v35 and the ones you define (using */ + /* `FT_Property_Set'). */ /* */ /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ /* defined. */ @@ -832,6 +841,33 @@ FT_BEGIN_HEADER /* #define CFF_CONFIG_OPTION_OLD_ENGINE */ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** P C F D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* There are many PCF fonts just called `Fixed' which look completely */ + /* different, and which have nothing to do with each other. When */ + /* selecting `Fixed' in KDE or Gnome one gets results that appear rather */ + /* random, the style changes often if one changes the size and one */ + /* cannot select some fonts at all. This option makes the PCF module */ + /* prepend the foundry name (plus a space) to the family name. */ + /* */ + /* We also check whether we have `wide' characters; all put together, we */ + /* get family names like `Sony Fixed' or `Misc Fixed Wide'. */ + /* */ + /* If this option is activated, it can be controlled with the */ + /* `no-long-family-names' property of the pcf driver module. */ + /* */ +/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + /*************************************************************************/ /*************************************************************************/ /**** ****/ @@ -850,7 +886,9 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ - /* Compile autofit module with Indic script support. */ + /* Compile autofit module with fallback Indic script support, covering */ + /* some scripts that the `latin' submodule of the autofit module doesn't */ + /* (yet) handle. */ /* */ #define AF_CONFIG_OPTION_INDIC @@ -869,6 +907,26 @@ FT_BEGIN_HEADER /* */ #define AF_CONFIG_OPTION_USE_WARPER + /*************************************************************************/ + /* */ + /* Use TrueType-like size metrics for `light' auto-hinting. */ + /* */ + /* It is strongly recommended to avoid this option, which exists only to */ + /* help some legacy applications retain its appearance and behaviour */ + /* with respect to auto-hinted TrueType fonts. */ + /* */ + /* The very reason this option exists at all are GNU/Linux distributions */ + /* like Fedora that did not un-patch the following change (which was */ + /* present in FreeType between versions 2.4.6 and 2.7.1, inclusive). */ + /* */ + /* 2011-07-16 Steven Chu */ + /* */ + /* [truetype] Fix metrics on size request for scalable fonts. */ + /* */ + /* This problematic commit is now reverted (more or less). */ + /* */ +/* #define AF_CONFIG_OPTION_TT_SIZE_METRICS */ + /* */ @@ -886,6 +944,7 @@ FT_BEGIN_HEADER #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING #if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 #define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY #endif @@ -893,6 +952,7 @@ FT_BEGIN_HEADER #if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #endif +#endif #endif diff --git a/Source/ThirdParty/FreeType/include/freetype/config/ftstdlib.h b/Source/ThirdParty/FreeType/include/freetype/config/ftstdlib.h index 6eefa9f86d..05a4845fd5 100644 --- a/Source/ThirdParty/FreeType/include/freetype/config/ftstdlib.h +++ b/Source/ThirdParty/FreeType/include/freetype/config/ftstdlib.h @@ -5,7 +5,7 @@ /* ANSI-specific library and header configuration file (specification */ /* only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/freetype.h b/Source/ThirdParty/FreeType/include/freetype/freetype.h index 08f59520c4..2989fbb5e1 100644 --- a/Source/ThirdParty/FreeType/include/freetype/freetype.h +++ b/Source/ThirdParty/FreeType/include/freetype/freetype.h @@ -4,7 +4,7 @@ /* */ /* FreeType high-level API and common types (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -175,6 +175,7 @@ FT_BEGIN_HEADER /* FT_Done_Face */ /* FT_Reference_Face */ /* FT_New_Memory_Face */ + /* FT_Face_Properties */ /* FT_Open_Face */ /* FT_Open_Args */ /* FT_Parameter */ @@ -265,8 +266,8 @@ FT_BEGIN_HEADER /* FT_Glyph_Metrics */ /* */ /* */ - /* A structure used to model the metrics of a single glyph. The */ - /* values are expressed in 26.6 fractional pixel format; if the flag */ + /* A structure to model the metrics of a single glyph. The values */ + /* are expressed in 26.6 fractional pixel format; if the flag */ /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */ /* are expressed in font units instead. */ /* */ @@ -305,6 +306,11 @@ FT_BEGIN_HEADER /* `horiAdvance' or `vertAdvance'; you have to manually adjust these */ /* values to account for the added width and height. */ /* */ + /* FreeType doesn't use the `VORG' table data for CFF fonts because */ + /* it doesn't have an interface to quickly retrieve the glyph height. */ + /* The y~coordinate of the vertical origin can be simply computed as */ + /* `vertBearingY + height' after loading a glyph. */ + /* */ typedef struct FT_Glyph_Metrics_ { FT_Pos width; @@ -349,10 +355,10 @@ FT_BEGIN_HEADER /* */ /* */ /* Windows FNT: */ - /* The nominal size given in a FNT font is not reliable. Thus when */ - /* the driver finds it incorrect, it sets `size' to some calculated */ - /* values and sets `x_ppem' and `y_ppem' to the pixel width and */ - /* height given in the font, respectively. */ + /* The nominal size given in a FNT font is not reliable. If the */ + /* driver finds it incorrect, it sets `size' to some calculated */ + /* values, and `x_ppem' and `y_ppem' to the pixel width and height */ + /* given in the font, respectively. */ /* */ /* TrueType embedded bitmaps: */ /* `size', `width', and `height' values are not contained in the */ @@ -421,9 +427,9 @@ FT_BEGIN_HEADER /* FT_Module */ /* */ /* */ - /* A handle to a given FreeType module object. Each module can be a */ + /* A handle to a given FreeType module object. A module can be a */ /* font driver, a renderer, or anything else that provides services */ - /* to the formers. */ + /* to the former. */ /* */ typedef struct FT_ModuleRec_* FT_Module; @@ -434,8 +440,8 @@ FT_BEGIN_HEADER /* FT_Driver */ /* */ /* */ - /* A handle to a given FreeType font driver object. Each font driver */ - /* is a special module capable of creating faces from font files. */ + /* A handle to a given FreeType font driver object. A font driver */ + /* is a module capable of creating faces from font files. */ /* */ typedef struct FT_DriverRec_* FT_Driver; @@ -446,10 +452,10 @@ FT_BEGIN_HEADER /* FT_Renderer */ /* */ /* */ - /* A handle to a given FreeType renderer. A renderer is a special */ - /* module in charge of converting a glyph image to a bitmap, when */ - /* necessary. Each renderer supports a given glyph image format, and */ - /* one or more target surface depths. */ + /* A handle to a given FreeType renderer. A renderer is a module in */ + /* charge of converting a glyph's outline image to a bitmap. It */ + /* supports a single glyph image format, and one or more target */ + /* surface depths. */ /* */ typedef struct FT_RendererRec_* FT_Renderer; @@ -467,15 +473,15 @@ FT_BEGIN_HEADER /* FT_Face */ /* */ /* */ - /* A handle to a given typographic face object. A face object models */ - /* a given typeface, in a given style. */ + /* A handle to a typographic face object. A face object models a */ + /* given typeface, in a given style. */ /* */ /* */ - /* Each face object also owns a single @FT_GlyphSlot object, as well */ + /* A face object also owns a single @FT_GlyphSlot object, as well */ /* as one or more @FT_Size objects. */ /* */ /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */ - /* a given filepathname or a custom input stream. */ + /* a given filepath or a custom input stream. */ /* */ /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */ /* */ @@ -500,11 +506,11 @@ FT_BEGIN_HEADER /* FT_Size */ /* */ /* */ - /* A handle to an object used to model a face scaled to a given */ + /* A handle to an object that models a face scaled to a given */ /* character size. */ /* */ /* */ - /* Each @FT_Face has an _active_ @FT_Size object that is used by */ + /* An @FT_Face has one _active_ @FT_Size object that is used by */ /* functions like @FT_Load_Glyph to determine the scaling */ /* transformation that in turn is used to load and hint glyphs and */ /* metrics. */ @@ -531,9 +537,8 @@ FT_BEGIN_HEADER /* FT_GlyphSlot */ /* */ /* */ - /* A handle to a given `glyph slot'. A slot is a container where it */ - /* is possible to load any of the glyphs contained in its parent */ - /* face. */ + /* A handle to a given `glyph slot'. A slot is a container that can */ + /* hold any of the glyphs contained in its parent face. */ /* */ /* In other words, each time you call @FT_Load_Glyph or */ /* @FT_Load_Char, the slot's content is erased by the new glyph data, */ @@ -552,13 +557,14 @@ FT_BEGIN_HEADER /* FT_CharMap */ /* */ /* */ - /* A handle to a given character map. A charmap is used to translate */ - /* character codes in a given encoding into glyph indexes for its */ - /* parent's face. Some font formats may provide several charmaps per */ - /* font. */ + /* A handle to a character map (usually abbreviated to `charmap'). A */ + /* charmap is used to translate character codes in a given encoding */ + /* into glyph indexes for its parent's face. Some font formats may */ + /* provide several charmaps per font. */ /* */ /* Each face object owns zero or more charmaps, but only one of them */ - /* can be `active' and used by @FT_Get_Char_Index or @FT_Load_Char. */ + /* can be `active', providing the data used by @FT_Get_Char_Index or */ + /* @FT_Load_Char. */ /* */ /* The list of available charmaps in a face is available through the */ /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */ @@ -615,8 +621,8 @@ FT_BEGIN_HEADER /* FT_Encoding */ /* */ /* */ - /* An enumeration used to specify character sets supported by */ - /* charmaps. Used in the @FT_Select_Charmap API function. */ + /* An enumeration to specify character sets supported by charmaps. */ + /* Used in the @FT_Select_Charmap API function. */ /* */ /* */ /* Despite the name, this enumeration lists specific character */ @@ -630,18 +636,17 @@ FT_BEGIN_HEADER /* The encoding value~0 is reserved. */ /* */ /* FT_ENCODING_UNICODE :: */ - /* Corresponds to the Unicode character set. This value covers */ - /* all versions of the Unicode repertoire, including ASCII and */ - /* Latin-1. Most fonts include a Unicode charmap, but not all */ - /* of them. */ + /* The Unicode character set. This value covers all versions of */ + /* the Unicode repertoire, including ASCII and Latin-1. Most fonts */ + /* include a Unicode charmap, but not all of them. */ /* */ /* For example, if you want to access Unicode value U+1F028 (and */ /* the font contains it), use value 0x1F028 as the input value for */ /* @FT_Get_Char_Index. */ /* */ /* FT_ENCODING_MS_SYMBOL :: */ - /* Corresponds to the Microsoft Symbol encoding, used to encode */ - /* mathematical symbols and wingdings. For more information, see */ + /* Microsoft Symbol encoding, used to encode mathematical symbols */ + /* and wingdings. For more information, see */ /* `http://www.microsoft.com/typography/otspec/recom.htm', */ /* `http://www.kostis.net/charsets/symbol.htm', and */ /* `http://www.kostis.net/charsets/wingding.htm'. */ @@ -650,60 +655,60 @@ FT_BEGIN_HEADER /* Area) in the range U+F020-U+F0FF. */ /* */ /* FT_ENCODING_SJIS :: */ - /* Corresponds to Japanese SJIS encoding. More info at */ - /* `http://en.wikipedia.org/wiki/Shift_JIS'. */ - /* See note on multi-byte encodings below. */ + /* Shift JIS encoding for Japanese. More info at */ + /* `http://en.wikipedia.org/wiki/Shift_JIS'. See note on */ + /* multi-byte encodings below. */ /* */ - /* FT_ENCODING_GB2312 :: */ - /* Corresponds to an encoding system for Simplified Chinese as */ - /* used in mainland China. */ + /* FT_ENCODING_PRC :: */ + /* Corresponds to encoding systems mainly for Simplified Chinese as */ + /* used in People's Republic of China (PRC). The encoding layout */ + /* is based on GB~2312 and its supersets GBK and GB~18030. */ /* */ /* FT_ENCODING_BIG5 :: */ /* Corresponds to an encoding system for Traditional Chinese as */ /* used in Taiwan and Hong Kong. */ /* */ /* FT_ENCODING_WANSUNG :: */ - /* Corresponds to the Korean encoding system known as Wansung. */ + /* Corresponds to the Korean encoding system known as Extended */ + /* Wansung (MS Windows code page 949). */ /* For more information see */ - /* `https://msdn.microsoft.com/en-US/goglobal/cc305154'. */ + /* `http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt'. */ /* */ /* FT_ENCODING_JOHAB :: */ /* The Korean standard character set (KS~C 5601-1992), which */ /* corresponds to MS Windows code page 1361. This character set */ - /* includes all possible Hangeul character combinations. */ + /* includes all possible Hangul character combinations. */ /* */ /* FT_ENCODING_ADOBE_LATIN_1 :: */ /* Corresponds to a Latin-1 encoding as defined in a Type~1 */ /* PostScript font. It is limited to 256 character codes. */ /* */ /* FT_ENCODING_ADOBE_STANDARD :: */ - /* Corresponds to the Adobe Standard encoding, as found in Type~1, */ - /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ - /* codes. */ + /* Adobe Standard encoding, as found in Type~1, CFF, and */ + /* OpenType/CFF fonts. It is limited to 256 character codes. */ /* */ /* FT_ENCODING_ADOBE_EXPERT :: */ - /* Corresponds to the Adobe Expert encoding, as found in Type~1, */ - /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ - /* codes. */ + /* Adobe Expert encoding, as found in Type~1, CFF, and OpenType/CFF */ + /* fonts. It is limited to 256 character codes. */ /* */ /* FT_ENCODING_ADOBE_CUSTOM :: */ /* Corresponds to a custom encoding, as found in Type~1, CFF, and */ /* OpenType/CFF fonts. It is limited to 256 character codes. */ /* */ /* FT_ENCODING_APPLE_ROMAN :: */ - /* Corresponds to the 8-bit Apple roman encoding. Many TrueType */ - /* and OpenType fonts contain a charmap for this encoding, since */ - /* older versions of Mac OS are able to use it. */ + /* Apple roman encoding. Many TrueType and OpenType fonts contain */ + /* a charmap for this 8-bit encoding, since older versions of Mac */ + /* OS are able to use it. */ /* */ /* FT_ENCODING_OLD_LATIN_2 :: */ - /* This value is deprecated and was never used nor reported by */ + /* This value is deprecated and was neither used nor reported by */ /* FreeType. Don't use or test for it. */ /* */ /* FT_ENCODING_MS_SJIS :: */ /* Same as FT_ENCODING_SJIS. Deprecated. */ /* */ /* FT_ENCODING_MS_GB2312 :: */ - /* Same as FT_ENCODING_GB2312. Deprecated. */ + /* Same as FT_ENCODING_PRC. Deprecated. */ /* */ /* FT_ENCODING_MS_BIG5 :: */ /* Same as FT_ENCODING_BIG5. Deprecated. */ @@ -716,7 +721,7 @@ FT_BEGIN_HEADER /* */ /* */ /* By default, FreeType automatically synthesizes a Unicode charmap */ - /* for PostScript fonts, using their glyph names dictionaries. */ + /* for PostScript fonts, using their glyph name dictionaries. */ /* However, it also reports the encodings defined explicitly in the */ /* font file, for the cases when they are needed, with the Adobe */ /* values as well. */ @@ -736,7 +741,7 @@ FT_BEGIN_HEADER /* Russian). */ /* */ /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */ - /* and `encoding_id' is not @TT_MAC_ID_ROMAN (otherwise it is set to */ + /* and `encoding_id' is not `TT_MAC_ID_ROMAN' (otherwise it is set to */ /* FT_ENCODING_APPLE_ROMAN). */ /* */ /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */ @@ -748,9 +753,9 @@ FT_BEGIN_HEADER /* to get an idea how to do that. Basically, if the language ID */ /* is~0, don't use it, otherwise subtract 1 from the language ID. */ /* Then examine `encoding_id'. If, for example, `encoding_id' is */ - /* @TT_MAC_ID_ROMAN and the language ID (minus~1) is */ + /* `TT_MAC_ID_ROMAN' and the language ID (minus~1) is */ /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */ - /* @TT_MAC_ID_ARABIC with `TT_MAC_LANGID_FARSI' means the Farsi */ + /* `TT_MAC_ID_ARABIC' with `TT_MAC_LANGID_FARSI' means the Farsi */ /* variant the Arabic encoding. */ /* */ typedef enum FT_Encoding_ @@ -761,14 +766,15 @@ FT_BEGIN_HEADER FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ), - FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ), + FT_ENC_TAG( FT_ENCODING_PRC, 'g', 'b', ' ', ' ' ), FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ), FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ), FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ), - /* for backwards compatibility */ + /* for backward compatibility */ + FT_ENCODING_GB2312 = FT_ENCODING_PRC, FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, - FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, + FT_ENCODING_MS_GB2312 = FT_ENCODING_PRC, FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, @@ -793,7 +799,7 @@ FT_BEGIN_HEADER #define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 #define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 #define ft_encoding_sjis FT_ENCODING_SJIS -#define ft_encoding_gb2312 FT_ENCODING_GB2312 +#define ft_encoding_gb2312 FT_ENCODING_PRC #define ft_encoding_big5 FT_ENCODING_BIG5 #define ft_encoding_wansung FT_ENCODING_WANSUNG #define ft_encoding_johab FT_ENCODING_JOHAB @@ -820,11 +826,11 @@ FT_BEGIN_HEADER /* */ /* platform_id :: An ID number describing the platform for the */ /* following encoding ID. This comes directly from */ - /* the TrueType specification and should be emulated */ - /* for other formats. */ + /* the TrueType specification and gets emulated for */ + /* other formats. */ /* */ /* encoding_id :: A platform specific encoding number. This also */ - /* comes from the TrueType specification and should be */ + /* comes from the TrueType specification and gets */ /* emulated similarly. */ /* */ typedef struct FT_CharMapRec_ @@ -852,8 +858,8 @@ FT_BEGIN_HEADER /* FT_Face_Internal */ /* */ /* */ - /* An opaque handle to an `FT_Face_InternalRec' structure, used to */ - /* model private data of a given @FT_Face object. */ + /* An opaque handle to an `FT_Face_InternalRec' structure that models */ + /* the private data of a given @FT_Face object. */ /* */ /* This structure might change between releases of FreeType~2 and is */ /* not generally available to client applications. */ @@ -873,7 +879,7 @@ FT_BEGIN_HEADER /* */ /* num_faces :: The number of faces in the font file. Some */ /* font formats can have multiple faces in */ - /* a font file. */ + /* a single font file. */ /* */ /* face_index :: This field holds two different values. */ /* Bits 0-15 are the index of the face in the */ @@ -881,14 +887,15 @@ FT_BEGIN_HEADER /* are set to~0 if there is only one face in */ /* the font file. */ /* */ - /* Bits 16-30 are relevant to GX variation */ - /* fonts only, holding the named instance */ - /* index for the current face index (starting */ - /* with value~1; value~0 indicates font access */ - /* without GX variation data). For non-GX */ - /* fonts, bits 16-30 are ignored. If we have */ - /* the third named instance of face~4, say, */ - /* `face_index' is set to 0x00030004. */ + /* Bits 16-30 are relevant to GX and OpenType */ + /* variation fonts only, holding the named */ + /* instance index for the current face index */ + /* (starting with value~1; value~0 indicates */ + /* font access without a named instance). For */ + /* non-variation fonts, bits 16-30 are */ + /* ignored. If we have the third named */ + /* instance of face~4, say, `face_index' is */ + /* set to 0x00030004. */ /* */ /* Bit 31 is always zero (this is, */ /* `face_index' is always a positive value). */ @@ -902,17 +909,21 @@ FT_BEGIN_HEADER /* @FT_STYLE_FLAG_XXX for the details. Bits */ /* 16-30 hold the number of named instances */ /* available for the current face if we have a */ - /* GX variation (sub)font. Bit 31 is always */ - /* zero (this is, `style_flags' is always a */ - /* positive value). */ + /* GX or OpenType variation (sub)font. Bit 31 */ + /* is always zero (this is, `style_flags' is */ + /* always a positive value). Note that a */ + /* variation font has always at least one */ + /* named instance, namely the default */ + /* instance. */ /* */ /* num_glyphs :: The number of glyphs in the face. If the */ /* face is scalable and has sbits (see */ /* `num_fixed_sizes'), it is set to the number */ /* of outline glyphs. */ /* */ - /* For CID-keyed fonts, this value gives the */ - /* highest CID used in the font. */ + /* For CID-keyed fonts (not in an SFNT */ + /* wrapper) this value gives the highest CID */ + /* used in the font. */ /* */ /* family_name :: The face's family name. This is an ASCII */ /* string, usually in English, that describes */ @@ -990,8 +1001,8 @@ FT_BEGIN_HEADER /* expressed in font units. For font formats */ /* not having this information, it is set to */ /* `bbox.yMin'. Note that this field is */ - /* usually negative. Only relevant for */ - /* scalable formats. */ + /* negative for values below the baseline. */ + /* Only relevant for scalable formats. */ /* */ /* height :: This value is the vertical distance */ /* between two consecutive baselines, */ @@ -1034,6 +1045,12 @@ FT_BEGIN_HEADER /* Fields may be changed after a call to @FT_Attach_File or */ /* @FT_Attach_Stream. */ /* */ + /* For an OpenType variation font, the values of the following fields */ + /* can change after a call to @FT_Set_Var_Design_Coordinates (and */ + /* friends) if the font contains an `MVAR' table: `ascender', */ + /* `descender', `height', `underline_position', and */ + /* `underline_thickness'. */ + /* */ typedef struct FT_FaceRec_ { FT_Long num_faces; @@ -1105,49 +1122,51 @@ FT_BEGIN_HEADER /* */ /* */ /* FT_FACE_FLAG_SCALABLE :: */ - /* Indicates that the face contains outline glyphs. This doesn't */ - /* prevent bitmap strikes, i.e., a face can have both this and */ + /* The face contains outline glyphs. Note that a face can contain */ + /* bitmap strikes also, i.e., a face can have both this flag and */ /* @FT_FACE_FLAG_FIXED_SIZES set. */ /* */ /* FT_FACE_FLAG_FIXED_SIZES :: */ - /* Indicates that the face contains bitmap strikes. See also the */ + /* The face contains bitmap strikes. See also the */ /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */ /* */ /* FT_FACE_FLAG_FIXED_WIDTH :: */ - /* Indicates that the face contains fixed-width characters (like */ - /* Courier, Lucido, MonoType, etc.). */ + /* The face contains fixed-width characters (like Courier, Lucida, */ + /* MonoType, etc.). */ /* */ /* FT_FACE_FLAG_SFNT :: */ - /* Indicates that the face uses the `sfnt' storage scheme. For */ - /* now, this means TrueType and OpenType. */ + /* The face uses the SFNT storage scheme. For now, this means */ + /* TrueType and OpenType. */ /* */ /* FT_FACE_FLAG_HORIZONTAL :: */ - /* Indicates that the face contains horizontal glyph metrics. This */ - /* should be set for all common formats. */ + /* The face contains horizontal glyph metrics. This should be set */ + /* for all common formats. */ /* */ /* FT_FACE_FLAG_VERTICAL :: */ - /* Indicates that the face contains vertical glyph metrics. This */ - /* is only available in some formats, not all of them. */ + /* The face contains vertical glyph metrics. This is only */ + /* available in some formats, not all of them. */ /* */ /* FT_FACE_FLAG_KERNING :: */ - /* Indicates that the face contains kerning information. If set, */ - /* the kerning distance can be retrieved through the function */ - /* @FT_Get_Kerning. Otherwise the function always return the */ - /* vector (0,0). Note that FreeType doesn't handle kerning data */ - /* from the `GPOS' table (as present in some OpenType fonts). */ + /* The face contains kerning information. If set, the kerning */ + /* distance can be retrieved using the function @FT_Get_Kerning. */ + /* Otherwise the function always return the vector (0,0). Note */ + /* that FreeType doesn't handle kerning data from the SFNT `GPOS' */ + /* table (as present in many OpenType fonts). */ /* */ /* FT_FACE_FLAG_FAST_GLYPHS :: */ /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */ /* */ /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */ - /* Indicates that the font contains multiple masters and is capable */ - /* of interpolating between them. See the multiple-masters */ - /* specific API for details. */ + /* The face contains multiple masters and is capable of */ + /* interpolating between them. Supported formats are Adobe MM, */ + /* TrueType GX, and OpenType variation fonts. */ + /* */ + /* See the multiple-masters specific API for details. */ /* */ /* FT_FACE_FLAG_GLYPH_NAMES :: */ - /* Indicates that the font contains glyph names that can be */ - /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */ - /* fonts contain broken glyph name tables. Use the function */ + /* The face contains glyph names, which can be retrieved using */ + /* @FT_Get_Glyph_Name. Note that some TrueType fonts contain */ + /* broken glyph name tables. Use the function */ /* @FT_Has_PS_Glyph_Names when needed. */ /* */ /* FT_FACE_FLAG_EXTERNAL_STREAM :: */ @@ -1156,31 +1175,31 @@ FT_BEGIN_HEADER /* when @FT_Done_Face is called. Don't read or test this flag. */ /* */ /* FT_FACE_FLAG_HINTER :: */ - /* Set if the font driver has a hinting machine of its own. For */ - /* example, with TrueType fonts, it makes sense to use data from */ - /* the SFNT `gasp' table only if the native TrueType hinting engine */ - /* (with the bytecode interpreter) is available and active. */ + /* The font driver has a hinting machine of its own. For example, */ + /* with TrueType fonts, it makes sense to use data from the SFNT */ + /* `gasp' table only if the native TrueType hinting engine (with */ + /* the bytecode interpreter) is available and active. */ /* */ /* FT_FACE_FLAG_CID_KEYED :: */ - /* Set if the font is CID-keyed. In that case, the font is not */ - /* accessed by glyph indices but by CID values. For subsetted */ - /* CID-keyed fonts this has the consequence that not all index */ - /* values are a valid argument to FT_Load_Glyph. Only the CID */ - /* values for which corresponding glyphs in the subsetted font */ - /* exist make FT_Load_Glyph return successfully; in all other cases */ - /* you get an `FT_Err_Invalid_Argument' error. */ - /* */ - /* Note that CID-keyed fonts that are in an SFNT wrapper don't */ - /* have this flag set since the glyphs are accessed in the normal */ - /* way (using contiguous indices); the `CID-ness' isn't visible to */ - /* the application. */ + /* The face is CID-keyed. In that case, the face is not accessed */ + /* by glyph indices but by CID values. For subsetted CID-keyed */ + /* fonts this has the consequence that not all index values are a */ + /* valid argument to @FT_Load_Glyph. Only the CID values for which */ + /* corresponding glyphs in the subsetted font exist make */ + /* `FT_Load_Glyph' return successfully; in all other cases you get */ + /* an `FT_Err_Invalid_Argument' error. */ + /* */ + /* Note that CID-keyed fonts that are in an SFNT wrapper (this is, */ + /* all OpenType/CFF fonts) don't have this flag set since the */ + /* glyphs are accessed in the normal way (using contiguous */ + /* indices); the `CID-ness' isn't visible to the application. */ /* */ /* FT_FACE_FLAG_TRICKY :: */ - /* Set if the font is `tricky', this is, it always needs the */ - /* font format's native hinting engine to get a reasonable result. */ - /* A typical example is the Chinese font `mingli.ttf' that uses */ - /* TrueType bytecode instructions to move and scale all of its */ - /* subglyphs. */ + /* The face is `tricky', this is, it always needs the font format's */ + /* native hinting engine to get a reasonable result. A typical */ + /* example is the old Chinese font `mingli.ttf' (but not */ + /* `mingliu.ttc') that uses TrueType bytecode instructions to move */ + /* and scale all of its subglyphs. */ /* */ /* It is not possible to auto-hint such fonts using */ /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */ @@ -1192,8 +1211,8 @@ FT_BEGIN_HEADER /* tricky fonts; they are hard-coded in file `ttobjs.c'. */ /* */ /* FT_FACE_FLAG_COLOR :: */ - /* Set if the font has color glyph tables. To access color glyphs */ - /* use @FT_LOAD_COLOR. */ + /* The face has color glyph tables. To access color glyphs use */ + /* @FT_LOAD_COLOR. */ /* */ #define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) #define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) @@ -1265,7 +1284,7 @@ FT_BEGIN_HEADER * @description: * A macro that returns true whenever a face object contains a scalable * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF, - * and PFR font formats. + * and PFR font formats). * */ #define FT_IS_SCALABLE( face ) \ @@ -1369,7 +1388,7 @@ FT_BEGIN_HEADER * * @description: * A macro that returns true whenever a face object is a named instance - * of a GX variation font. + * of a GX or OpenType variation font. * */ #define FT_IS_NAMED_INSTANCE( face ) \ @@ -1428,15 +1447,15 @@ FT_BEGIN_HEADER /* FT_STYLE_FLAG_XXX */ /* */ /* */ - /* A list of bit flags used to indicate the style of a given face. */ - /* These are used in the `style_flags' field of @FT_FaceRec. */ + /* A list of bit flags to indicate the style of a given face. These */ + /* are used in the `style_flags' field of @FT_FaceRec. */ /* */ /* */ /* FT_STYLE_FLAG_ITALIC :: */ - /* Indicates that a given face style is italic or oblique. */ + /* The face style is italic or oblique. */ /* */ /* FT_STYLE_FLAG_BOLD :: */ - /* Indicates that a given face is bold. */ + /* The face is bold. */ /* */ /* */ /* The style information as provided by FreeType is very basic. More */ @@ -1477,43 +1496,50 @@ FT_BEGIN_HEADER /* hence the term `ppem' (pixels per EM). It is also */ /* referred to as `nominal height'. */ /* */ - /* x_scale :: A 16.16 fractional scaling value used to convert */ + /* x_scale :: A 16.16 fractional scaling value to convert */ /* horizontal metrics from font units to 26.6 */ /* fractional pixels. Only relevant for scalable */ /* font formats. */ /* */ - /* y_scale :: A 16.16 fractional scaling value used to convert */ + /* y_scale :: A 16.16 fractional scaling value to convert */ /* vertical metrics from font units to 26.6 */ /* fractional pixels. Only relevant for scalable */ /* font formats. */ /* */ - /* ascender :: The ascender in 26.6 fractional pixels. See */ - /* @FT_FaceRec for the details. */ + /* ascender :: The ascender in 26.6 fractional pixels, rounded up */ + /* to an integer value. See @FT_FaceRec for the */ + /* details. */ /* */ - /* descender :: The descender in 26.6 fractional pixels. See */ - /* @FT_FaceRec for the details. */ + /* descender :: The descender in 26.6 fractional pixels, rounded */ + /* down to an integer value. See @FT_FaceRec for the */ + /* details. */ /* */ - /* height :: The height in 26.6 fractional pixels. See */ - /* @FT_FaceRec for the details. */ + /* height :: The height in 26.6 fractional pixels, rounded to */ + /* an integer value. See @FT_FaceRec for the */ + /* details. */ /* */ /* max_advance :: The maximum advance width in 26.6 fractional */ - /* pixels. See @FT_FaceRec for the details. */ + /* pixels, rounded to an integer value. See */ + /* @FT_FaceRec for the details. */ /* */ /* */ /* The scaling values, if relevant, are determined first during a */ /* size changing operation. The remaining fields are then set by the */ /* driver. For scalable formats, they are usually set to scaled */ - /* values of the corresponding fields in @FT_FaceRec. */ + /* values of the corresponding fields in @FT_FaceRec. Some values */ + /* like ascender or descender are rounded for historical reasons; */ + /* more precise values (for outline fonts) can be derived by scaling */ + /* the corresponding @FT_FaceRec values manually. */ /* */ - /* Note that due to glyph hinting, these values might not be exact */ - /* for certain fonts. Thus they must be treated as unreliable */ - /* with an error margin of at least one pixel! */ + /* Note that due to glyph hinting and the selected rendering mode */ + /* these values are usually not exact; consequently, they must be */ + /* treated as unreliable with an error margin of at least one pixel! */ /* */ /* Indeed, the only way to get the exact metrics is to render _all_ */ /* glyphs. As this would be a definite performance hit, it is up to */ /* client applications to perform such computations. */ /* */ - /* The FT_Size_Metrics structure is valid for bitmap fonts also. */ + /* The `FT_Size_Metrics' structure is valid for bitmap fonts also. */ /* */ typedef struct FT_Size_Metrics_ { @@ -1653,8 +1679,8 @@ FT_BEGIN_HEADER /* contained in the glyph slot. Typically */ /* @FT_GLYPH_FORMAT_BITMAP, */ /* @FT_GLYPH_FORMAT_OUTLINE, or */ - /* @FT_GLYPH_FORMAT_COMPOSITE, but others are */ - /* possible. */ + /* @FT_GLYPH_FORMAT_COMPOSITE, but other values */ + /* are possible. */ /* */ /* bitmap :: This field is used as a bitmap descriptor */ /* when the slot format is */ @@ -1669,16 +1695,15 @@ FT_BEGIN_HEADER /* glyph slot contains a bitmap. */ /* */ /* bitmap_top :: The bitmap's top bearing expressed in integer */ - /* pixels. Remember that this is the distance */ - /* from the baseline to the top-most glyph */ - /* scanline, upwards y~coordinates being */ - /* *positive*. */ + /* pixels. This is the distance from the */ + /* baseline to the top-most glyph scanline, */ + /* upwards y~coordinates being *positive*. */ /* */ /* outline :: The outline descriptor for the current glyph */ /* image if its format is */ /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */ /* loaded, `outline' can be transformed, */ - /* distorted, embolded, etc. However, it must */ + /* distorted, emboldened, etc. However, it must */ /* not be freed. */ /* */ /* num_subglyphs :: The number of subglyphs in a composite glyph. */ @@ -1694,15 +1719,13 @@ FT_BEGIN_HEADER /* control_data :: Certain font drivers can also return the */ /* control data for a given glyph image (e.g. */ /* TrueType bytecode, Type~1 charstrings, etc.). */ - /* This field is a pointer to such data. */ + /* This field is a pointer to such data; it is */ + /* currently internal to FreeType. */ /* */ /* control_len :: This is the length in bytes of the control */ - /* data. */ + /* data. Currently internal to FreeType. */ /* */ - /* other :: Really wicked formats can use this pointer to */ - /* present their own glyph image to client */ - /* applications. Note that the application */ - /* needs to know about the image format. */ + /* other :: Reserved. */ /* */ /* lsb_delta :: The difference between hinted and unhinted */ /* left side bearing while auto-hinting is */ @@ -1719,7 +1742,7 @@ FT_BEGIN_HEADER /* formats). */ /* */ /* This image can later be converted into a bitmap by calling */ - /* @FT_Render_Glyph. This function finds the current renderer for */ + /* @FT_Render_Glyph. This function searches the current renderer for */ /* the native image's format, then invokes it. */ /* */ /* The renderer is in charge of transforming the native image through */ @@ -1732,29 +1755,55 @@ FT_BEGIN_HEADER /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */ /* */ /* Here is a small pseudo code fragment that shows how to use */ - /* `lsb_delta' and `rsb_delta': */ + /* `lsb_delta' and `rsb_delta' to do fractional positioning of */ + /* glyphs: */ + /* */ + /* { */ + /* FT_GlyphSlot slot = face->glyph; */ + /* FT_Pos origin_x = 0; */ + /* */ + /* */ + /* for all glyphs do */ + /* */ + /* */ + /* FT_Outline_Translate( slot->outline, origin_x & 63, 0 ); */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* origin_x += slot->advance.x; */ + /* origin_x += slot->rsb_delta - slot->lsb_relta; */ + /* endfor */ + /* } */ + /* */ + /* Here is another small pseudo code fragment that shows how to use */ + /* `lsb_delta' and `rsb_delta' to improve integer positioning of */ + /* glyphs: */ /* */ /* { */ - /* FT_Pos origin_x = 0; */ - /* FT_Pos prev_rsb_delta = 0; */ + /* FT_GlyphSlot slot = face->glyph; */ + /* FT_Pos origin_x = 0; */ + /* FT_Pos prev_rsb_delta = 0; */ /* */ /* */ /* for all glyphs do */ - /* */ + /* */ /* */ /* */ /* */ - /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */ + /* if ( prev_rsb_delta - slot->lsb_delta >= 32 ) */ /* origin_x -= 64; */ - /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */ + /* else if ( prev_rsb_delta - slot->lsb_delta < -32 ) */ /* origin_x += 64; */ /* */ - /* prev_rsb_delta = face->glyph->rsb_delta; */ + /* prev_rsb_delta = slot->rsb_delta; */ /* */ /* */ /* */ - /* origin_x += face->glyph->advance.x; */ + /* origin_x += slot->advance.x; */ /* endfor */ /* } */ /* */ @@ -1828,7 +1877,8 @@ FT_BEGIN_HEADER /* */ /* In case you want to provide your own memory allocating routines, */ /* use @FT_New_Library instead, followed by a call to */ - /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module). */ + /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module) */ + /* and @FT_Set_Default_Properties. */ /* */ /* See the documentation of @FT_Library and @FT_Face for */ /* multi-threading issues. */ @@ -1836,6 +1886,11 @@ FT_BEGIN_HEADER /* If you need reference-counting (cf. @FT_Reference_Library), use */ /* @FT_New_Library and @FT_Done_Library. */ /* */ + /* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */ + /* set, this function reads the `FREETYPE_PROPERTIES' environment */ + /* variable to control driver properties. See sections @auto_hinter, */ + /* @cff_driver, @pcf_driver, and @tt_driver for more. */ + /* */ FT_EXPORT( FT_Error ) FT_Init_FreeType( FT_Library *alibrary ); @@ -1906,8 +1961,8 @@ FT_BEGIN_HEADER /* FT_Parameter */ /* */ /* */ - /* A simple structure used to pass more or less generic parameters to */ - /* @FT_Open_Face. */ + /* A simple structure to pass more or less generic parameters to */ + /* @FT_Open_Face and @FT_Face_Properties. */ /* */ /* */ /* tag :: A four-byte identification tag. */ @@ -1932,9 +1987,9 @@ FT_BEGIN_HEADER /* FT_Open_Args */ /* */ /* */ - /* A structure used to indicate how to open a new font file or */ - /* stream. A pointer to such a structure can be used as a parameter */ - /* for the functions @FT_Open_Face and @FT_Attach_Stream. */ + /* A structure to indicate how to open a new font file or stream. A */ + /* pointer to such a structure can be used as a parameter for the */ + /* functions @FT_Open_Face and @FT_Attach_Stream. */ /* */ /* */ /* flags :: A set of bit flags indicating how to use the */ @@ -1949,9 +2004,10 @@ FT_BEGIN_HEADER /* stream :: A handle to a source stream object. */ /* */ /* driver :: This field is exclusively used by @FT_Open_Face; */ - /* it simply specifies the font driver to use to open */ - /* the face. If set to~0, FreeType tries to load the */ - /* face with each one of the drivers in its list. */ + /* it simply specifies the font driver to use for */ + /* opening the face. If set to NULL, FreeType tries */ + /* to load the face with each one of the drivers in */ + /* its list. */ /* */ /* num_params :: The number of extra parameters. */ /* */ @@ -1981,7 +2037,7 @@ FT_BEGIN_HEADER /* `num_params' and `params' is used. They are ignored otherwise. */ /* */ /* Ideally, both the `pathname' and `params' fields should be tagged */ - /* as `const'; this is missing for API backwards compatibility. In */ + /* as `const'; this is missing for API backward compatibility. In */ /* other words, applications should treat them as read-only. */ /* */ typedef struct FT_Open_Args_ @@ -2004,7 +2060,7 @@ FT_BEGIN_HEADER /* FT_New_Face */ /* */ /* */ - /* This function calls @FT_Open_Face to open a font by its pathname. */ + /* Call @FT_Open_Face to open a font by its pathname. */ /* */ /* */ /* library :: A handle to the library resource. */ @@ -2039,8 +2095,8 @@ FT_BEGIN_HEADER /* FT_New_Memory_Face */ /* */ /* */ - /* This function calls @FT_Open_Face to open a font that has been */ - /* loaded into memory. */ + /* Call @FT_Open_Face to open a font that has been loaded into */ + /* memory. */ /* */ /* */ /* library :: A handle to the library resource. */ @@ -2092,20 +2148,21 @@ FT_BEGIN_HEADER /* with value~0). Set it to~0 if there is only one */ /* face in the font file. */ /* */ - /* Bits 16-30 are relevant to GX variation fonts only, */ - /* specifying the named instance index for the current */ - /* face index (starting with value~1; value~0 makes */ - /* FreeType ignore named instances). For non-GX fonts, */ - /* bits 16-30 are ignored. Assuming that you want to */ - /* access the third named instance in face~4, */ - /* `face_index' should be set to 0x00030004. If you */ - /* want to access face~4 without GX variation handling, */ - /* simply set `face_index' to value~4. */ - /* */ - /* FT_Open_Face and its siblings can be used to quickly */ - /* check whether the font format of a given font */ - /* resource is supported by FreeType. In general, if */ - /* the `face_index' argument is negative, the */ + /* Bits 16-30 are relevant to GX and OpenType variation */ + /* fonts only, specifying the named instance index for */ + /* the current face index (starting with value~1; */ + /* value~0 makes FreeType ignore named instances). For */ + /* non-variation fonts, bits 16-30 are ignored. */ + /* Assuming that you want to access the third named */ + /* instance in face~4, `face_index' should be set to */ + /* 0x00030004. If you want to access face~4 without */ + /* variation handling, simply set `face_index' to */ + /* value~4. */ + /* */ + /* `FT_Open_Face' and its siblings can be used to */ + /* quickly check whether the font format of a given */ + /* font resource is supported by FreeType. In general, */ + /* if the `face_index' argument is negative, the */ /* function's return value is~0 if the font format is */ /* recognized, or non-zero otherwise. The function */ /* allocates a more or less empty face handle in */ @@ -2114,10 +2171,10 @@ FT_BEGIN_HEADER /* `face->num_faces' and `face->style_flags'. For any */ /* negative value of `face_index', `face->num_faces' */ /* gives the number of faces within the font file. For */ - /* the negative value `-(N+1)' (with `N' a 16-bit */ - /* value), bits 16-30 in `face->style_flags' give the */ - /* number of named instances in face `N' if we have a */ - /* GX variation font (or zero otherwise). After */ + /* the negative value `-(N+1)' (with `N' a non-negative */ + /* 16-bit value), bits 16-30 in `face->style_flags' */ + /* give the number of named instances in face `N' if we */ + /* have a variation font (or zero otherwise). After */ /* examination, the returned @FT_Face structure should */ /* be deallocated with a call to @FT_Done_Face. */ /* */ @@ -2224,7 +2281,7 @@ FT_BEGIN_HEADER /* FT_Attach_File */ /* */ /* */ - /* This function calls @FT_Attach_Stream to attach a file. */ + /* Call @FT_Attach_Stream to attach a file. */ /* */ /* */ /* face :: The target face object. */ @@ -2268,7 +2325,7 @@ FT_BEGIN_HEADER /* */ /* Client applications are expected to know what they are doing */ /* when invoking this function. Most drivers simply do not implement */ - /* file attachments. */ + /* file or stream attachments. */ /* */ FT_EXPORT( FT_Error ) FT_Attach_Stream( FT_Face face, @@ -2352,11 +2409,11 @@ FT_BEGIN_HEADER /* FreeType silently uses outlines if there is no bitmap for a given */ /* glyph index. */ /* */ - /* For GX variation fonts, a bitmap strike makes sense only if the */ - /* default instance is active (this is, no glyph variation takes */ - /* place); otherwise, FreeType simply ignores bitmap strikes. The */ - /* same is true for all named instances that are different from the */ - /* default instance. */ + /* For GX and OpenType variation fonts, a bitmap strike makes sense */ + /* only if the default instance is active (this is, no glyph */ + /* variation takes place); otherwise, FreeType simply ignores bitmap */ + /* strikes. The same is true for all named instances that are */ + /* different from the default instance. */ /* */ /* Don't use this function if you are using the FreeType cache API. */ /* */ @@ -2389,7 +2446,7 @@ FT_BEGIN_HEADER /* */ /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */ /* The real dimension. The sum of the `ascender' and (minus of) */ - /* the `descender' fields of @FT_FaceRec are used to determine both */ + /* the `descender' fields of @FT_FaceRec is used to determine both */ /* scaling values. */ /* */ /* FT_SIZE_REQUEST_TYPE_BBOX :: */ @@ -2435,7 +2492,7 @@ FT_BEGIN_HEADER /* FT_Size_RequestRec */ /* */ /* */ - /* A structure used to model a size request. */ + /* A structure to model a size request. */ /* */ /* */ /* type :: See @FT_Size_Request_Type. */ @@ -2448,14 +2505,16 @@ FT_BEGIN_HEADER /* */ /* horiResolution :: The horizontal resolution (dpi, i.e., pixels per */ /* inch). If set to zero, `width' is treated as a */ - /* 26.6 fractional *pixel* value. */ + /* 26.6 fractional *pixel* value, which gets */ + /* internally rounded to an integer. */ /* */ /* vertResolution :: The vertical resolution (dpi, i.e., pixels per */ /* inch). If set to zero, `height' is treated as a */ - /* 26.6 fractional *pixel* value. */ + /* 26.6 fractional *pixel* value, which gets */ + /* internally rounded to an integer. */ /* */ /* */ - /* If `width' is zero, then the horizontal scaling value is set equal */ + /* If `width' is zero, the horizontal scaling value is set equal */ /* to the vertical scaling value, and vice versa. */ /* */ /* If `type' is FT_SIZE_REQUEST_TYPE_SCALES, `width' and `height' are */ @@ -2512,7 +2571,11 @@ FT_BEGIN_HEADER /* size is dependent entirely on how the size is defined in the */ /* source face. The font designer chooses the final size of each */ /* glyph relative to this size. For more information refer to */ - /* `http://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html' */ + /* `https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'. */ + /* */ + /* Contrary to @FT_Set_Char_Size, this function doesn't have special */ + /* code to normalize zero-valued widths, heights, or resolutions */ + /* (which lead to errors in most cases). */ /* */ /* Don't use this function if you are using the FreeType cache API. */ /* */ @@ -2527,8 +2590,7 @@ FT_BEGIN_HEADER /* FT_Set_Char_Size */ /* */ /* */ - /* This function calls @FT_Request_Size to request the nominal size */ - /* (in points). */ + /* Call @FT_Request_Size to request the nominal size (in points). */ /* */ /* */ /* face :: A handle to a target face object. */ @@ -2546,6 +2608,10 @@ FT_BEGIN_HEADER /* FreeType error code. 0~means success. */ /* */ /* */ + /* While this function allows fractional points as input values, the */ + /* resulting ppem value for the given resolution is always rounded to */ + /* the nearest integer. */ + /* */ /* If either the character width or height is zero, it is set equal */ /* to the other value. */ /* */ @@ -2571,8 +2637,7 @@ FT_BEGIN_HEADER /* FT_Set_Pixel_Sizes */ /* */ /* */ - /* This function calls @FT_Request_Size to request the nominal size */ - /* (in pixels). */ + /* Call @FT_Request_Size to request the nominal size (in pixels). */ /* */ /* */ /* face :: A handle to the target face object. */ @@ -2586,8 +2651,8 @@ FT_BEGIN_HEADER /* FreeType error code. 0~means success. */ /* */ /* */ - /* You should not rely on the resulting glyphs matching, or being */ - /* constrained, to this pixel size. Refer to @FT_Request_Size to */ + /* You should not rely on the resulting glyphs matching or being */ + /* constrained to this pixel size. Refer to @FT_Request_Size to */ /* understand how requested sizes relate to actual sizes. */ /* */ /* Don't use this function if you are using the FreeType cache API. */ @@ -2604,8 +2669,7 @@ FT_BEGIN_HEADER /* FT_Load_Glyph */ /* */ /* */ - /* A function used to load a single glyph into the glyph slot of a */ - /* face object. */ + /* Load a glyph into the glyph slot of a face object. */ /* */ /* */ /* face :: A handle to the target face object where the glyph */ @@ -2650,8 +2714,8 @@ FT_BEGIN_HEADER /* FT_Load_Char */ /* */ /* */ - /* A function used to load a single glyph into the glyph slot of a */ - /* face object, according to its character code. */ + /* Load a glyph into the glyph slot of a face object, accessed by its */ + /* character code. */ /* */ /* */ /* face :: A handle to a target face object where the glyph */ @@ -2673,6 +2737,10 @@ FT_BEGIN_HEADER /* */ /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */ /* */ + /* Many fonts contain glyphs that can't be loaded by this function */ + /* since its glyph indices are not listed in any of the font's */ + /* charmaps. */ + /* */ FT_EXPORT( FT_Error ) FT_Load_Char( FT_Face face, FT_ULong char_code, @@ -2685,8 +2753,8 @@ FT_BEGIN_HEADER * FT_LOAD_XXX * * @description: - * A list of bit field constants used with @FT_Load_Glyph to indicate - * what kind of operations to perform during glyph loading. + * A list of bit field constants for @FT_Load_Glyph to indicate what + * kind of operations to perform during glyph loading. * * @values: * FT_LOAD_DEFAULT :: @@ -2698,13 +2766,13 @@ FT_BEGIN_HEADER * The bitmap data can be accessed from the glyph slot (see note * below). * - * 2. If no embedded bitmap is searched or found, FreeType looks for a - * scalable outline. If one is found, it is loaded from the font - * file, scaled to device pixels, then `hinted' to the pixel grid - * in order to optimize it. The outline data can be accessed from - * the glyph slot (see note below). + * 2. If no embedded bitmap is searched for or found, FreeType looks + * for a scalable outline. If one is found, it is loaded from + * the font file, scaled to device pixels, then `hinted' to the + * pixel grid in order to optimize it. The outline data can be + * accessed from the glyph slot (see note below). * - * Note that by default, the glyph loader doesn't render outlines into + * Note that by default the glyph loader doesn't render outlines into * bitmaps. The following flags are used to modify this default * behaviour to more specific and useful cases. * @@ -2751,13 +2819,13 @@ FT_BEGIN_HEADER * various font formats. * * FT_LOAD_FORCE_AUTOHINT :: - * Indicates that the auto-hinter is preferred over the font's native - * hinter. See also the note below. + * Prefer the auto-hinter over the font's native hinter. See also + * the note below. * * FT_LOAD_PEDANTIC :: - * Indicates that the font driver should perform pedantic verifications - * during glyph loading. This is mostly used to detect broken glyphs - * in fonts. By default, FreeType tries to handle broken fonts also. + * Make the font driver perform pedantic verifications during glyph + * loading. This is mostly used to detect broken glyphs in fonts. + * By default, FreeType tries to handle broken fonts also. * * In particular, errors from the TrueType bytecode engine are not * passed to the application if this flag is not set; this might @@ -2765,17 +2833,16 @@ FT_BEGIN_HEADER * bytecode is buggy. * * FT_LOAD_NO_RECURSE :: - * Indicate that the font driver should not load composite glyphs - * recursively. Instead, it should set the `num_subglyph' and - * `subglyphs' values of the glyph slot accordingly, and set - * `glyph->format' to @FT_GLYPH_FORMAT_COMPOSITE. The description of - * subglyphs can then be accessed with @FT_Get_SubGlyph_Info. + * Don't load composite glyphs recursively. Instead, the font + * driver should set the `num_subglyph' and `subglyphs' values of + * the glyph slot accordingly, and set `glyph->format' to + * @FT_GLYPH_FORMAT_COMPOSITE. The description of subglyphs can + * then be accessed with @FT_Get_SubGlyph_Info. * * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM. * * FT_LOAD_IGNORE_TRANSFORM :: - * Indicates that the transform matrix set by @FT_Set_Transform should - * be ignored. + * Ignore the transform matrix set by @FT_Set_Transform. * * FT_LOAD_MONOCHROME :: * This flag is used with @FT_LOAD_RENDER to indicate that you want to @@ -2787,36 +2854,34 @@ FT_BEGIN_HEADER * monochrome-optimized hinting algorithm is used. * * FT_LOAD_LINEAR_DESIGN :: - * Indicates that the `linearHoriAdvance' and `linearVertAdvance' - * fields of @FT_GlyphSlotRec should be kept in font units. See - * @FT_GlyphSlotRec for details. + * Keep `linearHoriAdvance' and `linearVertAdvance' fields of + * @FT_GlyphSlotRec in font units. See @FT_GlyphSlotRec for + * details. * * FT_LOAD_NO_AUTOHINT :: - * Disable auto-hinter. See also the note below. + * Disable the auto-hinter. See also the note below. * * FT_LOAD_COLOR :: - * This flag is used to request loading of color embedded-bitmap - * images. The resulting color bitmaps, if available, will have the - * @FT_PIXEL_MODE_BGRA format. When the flag is not used and color - * bitmaps are found, they will be converted to 256-level gray - * bitmaps transparently. Those bitmaps will be in the + * Load embedded color bitmap images. The resulting color bitmaps, + * if available, will have the @FT_PIXEL_MODE_BGRA format. If the + * flag is not set and color bitmaps are found, they are converted + * to 256-level gray bitmaps transparently, using the * @FT_PIXEL_MODE_GRAY format. * * FT_LOAD_COMPUTE_METRICS :: - * This flag sets computing glyph metrics without the use of bundled - * metrics tables (for example, the `hdmx' table in TrueType fonts). - * Well-behaving fonts have optimized bundled metrics and these should - * be used. This flag is mainly used by font validating or font + * Compute glyph metrics from the glyph data, without the use of + * bundled metrics tables (for example, the `hdmx' table in TrueType + * fonts). This flag is mainly used by font validating or font * editing applications, which need to ignore, verify, or edit those * tables. * * Currently, this flag is only implemented for TrueType fonts. * * FT_LOAD_BITMAP_METRICS_ONLY :: - * This flag is used to request loading of the metrics and bitmap - * image information of a (possibly embedded) bitmap glyph without - * allocating or copying the bitmap image data itself. No effect if - * the target glyph is not a bitmap image. + * Request loading of the metrics and bitmap image information of a + * (possibly embedded) bitmap glyph without allocating or copying + * the bitmap image data itself. No effect if the target glyph is + * not a bitmap image. * * This flag unsets @FT_LOAD_RENDER. * @@ -2863,14 +2928,14 @@ FT_BEGIN_HEADER #define FT_LOAD_MONOCHROME ( 1L << 12 ) #define FT_LOAD_LINEAR_DESIGN ( 1L << 13 ) #define FT_LOAD_NO_AUTOHINT ( 1L << 15 ) - /* Bits 16..19 are used by `FT_LOAD_TARGET_' */ + /* Bits 16-19 are used by `FT_LOAD_TARGET_' */ #define FT_LOAD_COLOR ( 1L << 20 ) #define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) #define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) /* */ - /* used internally only by certain font drivers! */ + /* used internally only by certain font drivers */ #define FT_LOAD_ADVANCE_ONLY ( 1L << 8 ) #define FT_LOAD_SBITS_ONLY ( 1L << 14 ) @@ -2881,37 +2946,48 @@ FT_BEGIN_HEADER * FT_LOAD_TARGET_XXX * * @description: - * A list of values that are used to select a specific hinting algorithm - * to use by the hinter. You should OR one of these values to your - * `load_flags' when calling @FT_Load_Glyph. + * A list of values to select a specific hinting algorithm for the + * hinter. You should OR one of these values to your `load_flags' + * when calling @FT_Load_Glyph. * - * Note that font's native hinters may ignore the hinting algorithm you - * have specified (e.g., the TrueType bytecode interpreter). You can set - * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. + * Note that a font's native hinters may ignore the hinting algorithm + * you have specified (e.g., the TrueType bytecode interpreter). You + * can set @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is + * used. * * @values: * FT_LOAD_TARGET_NORMAL :: - * This corresponds to the default hinting algorithm, optimized for - * standard gray-level rendering. For monochrome output, use - * @FT_LOAD_TARGET_MONO instead. + * The default hinting algorithm, optimized for standard gray-level + * rendering. For monochrome output, use @FT_LOAD_TARGET_MONO + * instead. * * FT_LOAD_TARGET_LIGHT :: * A lighter hinting algorithm for gray-level modes. Many generated * glyphs are fuzzier but better resemble their original shape. This * is achieved by snapping glyphs to the pixel grid only vertically - * (Y-axis), as is done by Microsoft's ClearType and Adobe's - * proprietary font renderer. This preserves inter-glyph spacing in + * (Y-axis), as is done by FreeType's new CFF engine or Microsoft's + * ClearType font renderer. This preserves inter-glyph spacing in * horizontal text. The snapping is done either by the native font - * driver if the driver itself and the font support it or by the + * driver, if the driver itself and the font support it, or by the * auto-hinter. * + * Advance widths are rounded to integer values; however, using the + * `lsb_delta' and `rsb_delta' fields of @FT_GlyphSlotRec, it is + * possible to get fractional advance widths for sub-pixel positioning + * (which is recommended to use). + * + * If configuration option AF_CONFIG_OPTION_TT_SIZE_METRICS is active, + * TrueType-like metrics are used to make this mode behave similarly + * as in unpatched FreeType versions between 2.4.6 and 2.7.1 + * (inclusive). + * * FT_LOAD_TARGET_MONO :: * Strong hinting algorithm that should only be used for monochrome * output. The result is probably unpleasant if the glyph is rendered * in non-monochrome modes. * * FT_LOAD_TARGET_LCD :: - * A variant of @FT_LOAD_TARGET_NORMAL optimized for horizontally + * A variant of @FT_LOAD_TARGET_LIGHT optimized for horizontally * decimated LCD displays. * * FT_LOAD_TARGET_LCD_V :: @@ -2939,6 +3015,13 @@ FT_BEGIN_HEADER * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); * } * + * In general, you should stick with one rendering mode. For example, + * switching between @FT_LOAD_TARGET_NORMAL and @FT_LOAD_TARGET_MONO + * enforces a lot of recomputation for TrueType fonts, which is slow. + * Another reason is caching: Selecting a different mode usually causes + * changes in both the outlines and the rasterized bitmaps; it is thus + * necessary to empty the cache after a mode switch to avoid false hits. + * */ #define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 ) @@ -2968,18 +3051,17 @@ FT_BEGIN_HEADER /* FT_Set_Transform */ /* */ /* */ - /* A function used to set the transformation that is applied to glyph */ - /* images when they are loaded into a glyph slot through */ - /* @FT_Load_Glyph. */ + /* Set the transformation that is applied to glyph images when they */ + /* are loaded into a glyph slot through @FT_Load_Glyph. */ /* */ /* */ /* face :: A handle to the source face object. */ /* */ /* */ - /* matrix :: A pointer to the transformation's 2x2 matrix. Use~0 for */ - /* the identity matrix. */ - /* delta :: A pointer to the translation vector. Use~0 for the null */ - /* vector. */ + /* matrix :: A pointer to the transformation's 2x2 matrix. Use NULL */ + /* for the identity matrix. */ + /* delta :: A pointer to the translation vector. Use NULL for the */ + /* null vector. */ /* */ /* */ /* The transformation is only applied to scalable image formats after */ @@ -3002,9 +3084,8 @@ FT_BEGIN_HEADER /* FT_Render_Mode */ /* */ /* */ - /* An enumeration type that lists the render modes supported by */ - /* FreeType~2. Each mode corresponds to a specific type of scanline */ - /* conversion performed on the outline. */ + /* Render modes supported by FreeType~2. Each mode corresponds to a */ + /* specific type of scanline conversion performed on the outline. */ /* */ /* For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode' */ /* field in the @FT_GlyphSlotRec structure gives the format of the */ @@ -3017,8 +3098,8 @@ FT_BEGIN_HEADER /* */ /* */ /* FT_RENDER_MODE_NORMAL :: */ - /* This is the default render mode; it corresponds to 8-bit */ - /* anti-aliased bitmaps. */ + /* Default render mode; it corresponds to 8-bit anti-aliased */ + /* bitmaps. */ /* */ /* FT_RENDER_MODE_LIGHT :: */ /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */ @@ -3043,11 +3124,11 @@ FT_BEGIN_HEADER /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */ /* */ /* */ - /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph can be */ - /* filtered to reduce color-fringes by using @FT_Library_SetLcdFilter */ - /* (not active in the default builds). It is up to the caller to */ - /* either call @FT_Library_SetLcdFilter (if available) or do the */ - /* filtering itself. */ + /* The LCD-optimized glyph bitmaps produced by `FT_Render_Glyph' can */ + /* be filtered to reduce color-fringes by using */ + /* @FT_Library_SetLcdFilter (not active in the default builds). It */ + /* is up to the caller to either call `FT_Library_SetLcdFilter' (if */ + /* available) or do the filtering itself. */ /* */ /* The selected render mode only affects vector glyphs of a font. */ /* Embedded bitmaps often have a different pixel mode like */ @@ -3088,16 +3169,16 @@ FT_BEGIN_HEADER /* convert. */ /* */ /* */ - /* render_mode :: This is the render mode used to render the glyph */ - /* image into a bitmap. See @FT_Render_Mode for a */ - /* list of possible values. */ + /* render_mode :: The render mode used to render the glyph image into */ + /* a bitmap. See @FT_Render_Mode for a list of */ + /* possible values. */ /* */ /* */ /* FreeType error code. 0~means success. */ /* */ /* */ /* To get meaningful results, font scaling values must be set with */ - /* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */ + /* functions like @FT_Set_Char_Size before calling `FT_Render_Glyph'. */ /* */ /* When FreeType outputs a bitmap of a glyph, it really outputs an */ /* alpha coverage map. If a pixel is completely covered by a */ @@ -3123,7 +3204,7 @@ FT_BEGIN_HEADER /* this does not translate to 50% brightness for that pixel on our */ /* sRGB and gamma~2.2 screens. Due to their non-linearity, they */ /* dwell longer in the darks and only a pixel value of about 186 */ - /* results in 50% brightness – 128 ends up too dark on both bright */ + /* results in 50% brightness -- 128 ends up too dark on both bright */ /* and dark backgrounds. The net result is that dark text looks */ /* burnt-out, pixely and blotchy on bright background, bright text */ /* too frail on dark backgrounds, and colored text on colored */ @@ -3187,17 +3268,15 @@ FT_BEGIN_HEADER /* FT_Kerning_Mode */ /* */ /* */ - /* An enumeration used to specify which kerning values to return in */ + /* An enumeration to specify the format of kerning values returned by */ /* @FT_Get_Kerning. */ /* */ /* */ /* FT_KERNING_DEFAULT :: Return grid-fitted kerning distances in */ - /* pixels (value is~0). Whether they are */ - /* scaled depends on @FT_LOAD_NO_SCALE. */ + /* 26.6 fractional pixels. */ /* */ /* FT_KERNING_UNFITTED :: Return un-grid-fitted kerning distances in */ - /* 26.6 fractional pixels. Whether they are */ - /* scaled depends on @FT_LOAD_NO_SCALE. */ + /* 26.6 fractional pixels. */ /* */ /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */ /* units. */ @@ -3207,9 +3286,13 @@ FT_BEGIN_HEADER /* FreeType heuristically scale down kerning distances at small ppem */ /* values so that they don't become too big. */ /* */ + /* Both FT_KERNING_DEFAULT and FT_KERNING_UNFITTED use the current */ + /* horizontal scaling factor (as set e.g. with @FT_Set_Char_Size) to */ + /* convert font units to pixels. */ + /* */ typedef enum FT_Kerning_Mode_ { - FT_KERNING_DEFAULT = 0, + FT_KERNING_DEFAULT = 0, FT_KERNING_UNFITTED, FT_KERNING_UNSCALED @@ -3229,7 +3312,7 @@ FT_BEGIN_HEADER /* FT_Get_Kerning */ /* */ /* */ - /* Return the kerning vector between two glyphs of a same face. */ + /* Return the kerning vector between two glyphs of the same face. */ /* */ /* */ /* face :: A handle to a source face object. */ @@ -3257,6 +3340,10 @@ FT_BEGIN_HEADER /* kernings, are out of the scope of this API function -- they can be */ /* implemented through format-specific interfaces. */ /* */ + /* Kerning for OpenType fonts implemented in a `GPOS' table is not */ + /* supported; use @FT_HAS_KERNING to find out whether a font has data */ + /* that can be extracted with `FT_Get_Kerning'. */ + /* */ FT_EXPORT( FT_Error ) FT_Get_Kerning( FT_Face face, FT_UInt left_glyph, @@ -3296,7 +3383,7 @@ FT_BEGIN_HEADER /* @FT_Attach_Stream). */ /* */ /* Only very few AFM files come with track kerning data; please refer */ - /* to the Adobe's AFM specification for more details. */ + /* to Adobe's AFM specification for more details. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Track_Kerning( FT_Face face, @@ -3358,7 +3445,7 @@ FT_BEGIN_HEADER /* */ /* */ /* Retrieve the ASCII PostScript name of a given face, if available. */ - /* This only works with PostScript and TrueType fonts. */ + /* This only works with PostScript, TrueType, and OpenType fonts. */ /* */ /* */ /* face :: A handle to the source face object. */ @@ -3370,6 +3457,13 @@ FT_BEGIN_HEADER /* The returned pointer is owned by the face and is destroyed with */ /* it. */ /* */ + /* For variation fonts, this string changes if you select a different */ + /* instance, and you have to call `FT_Get_PostScript_Name' again to */ + /* retrieve it. FreeType follows Adobe TechNote #5902, `Generating */ + /* PostScript Names for Fonts Using OpenType Font Variations'. */ + /* */ + /* http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5902.AdobePSNameGeneration.html */ + /* */ FT_EXPORT( const char* ) FT_Get_Postscript_Name( FT_Face face ); @@ -3429,7 +3523,8 @@ FT_BEGIN_HEADER /* the face (i.e., if it is not listed in the `face->charmaps' */ /* table). */ /* */ - /* It also fails if a type~14 charmap is selected. */ + /* It also fails if an OpenType type~14 charmap is selected (which */ + /* doesn't map character codes to glyph indices at all). */ /* */ FT_EXPORT( FT_Error ) FT_Set_Charmap( FT_Face face, @@ -3464,7 +3559,7 @@ FT_BEGIN_HEADER /* */ /* */ /* Return the glyph index of a given character code. This function */ - /* uses a charmap object to do the mapping. */ + /* uses the currently selected charmap to do the mapping. */ /* */ /* */ /* face :: A handle to the source face object. */ @@ -3498,9 +3593,8 @@ FT_BEGIN_HEADER /* FT_Get_First_Char */ /* */ /* */ - /* This function is used to return the first character code in the */ - /* current charmap of a given face. It also returns the */ - /* corresponding glyph index. */ + /* Return the first character code in the current charmap of a given */ + /* face, together with its corresponding glyph index. */ /* */ /* */ /* face :: A handle to the source face object. */ @@ -3513,7 +3607,7 @@ FT_BEGIN_HEADER /* The charmap's first character code. */ /* */ /* */ - /* You should use this function with @FT_Get_Next_Char to be able to */ + /* You should use this function together with @FT_Get_Next_Char to */ /* parse all character codes available in a given charmap. The code */ /* should look like this: */ /* */ @@ -3553,12 +3647,13 @@ FT_BEGIN_HEADER /* FT_Get_Next_Char */ /* */ /* */ - /* This function is used to return the next character code in the */ - /* current charmap of a given face following the value `char_code', */ - /* as well as the corresponding glyph index. */ + /* Return the next character code in the current charmap of a given */ + /* face following the value `char_code', as well as the corresponding */ + /* glyph index. */ /* */ /* */ /* face :: A handle to the source face object. */ + /* */ /* char_code :: The starting character code. */ /* */ /* */ @@ -3571,7 +3666,7 @@ FT_BEGIN_HEADER /* */ /* You should use this function with @FT_Get_First_Char to walk */ /* over all character codes available in a given charmap. See the */ - /* note for this function for a simple code example. */ + /* note for that function for a simple code example. */ /* */ /* Note that `*agindex' is set to~0 when there are no more codes in */ /* the charmap. */ @@ -3582,14 +3677,109 @@ FT_BEGIN_HEADER FT_UInt *agindex ); + /************************************************************************* + * + * @function: + * FT_Face_Properties + * + * @description: + * Set or override certain (library or module-wide) properties on a + * face-by-face basis. Useful for finer-grained control and avoiding + * locks on shared structures (threads can modify their own faces as + * they see fit). + * + * Contrary to @FT_Property_Set, this function uses @FT_Parameter so + * that you can pass multiple properties to the target face in one call. + * Note that only a subset of the available properties can be + * controlled. + * + * * Stem darkening (@FT_PARAM_TAG_STEM_DARKENING, corresponding to the + * property `no-stem-darkening' provided by the `autofit' and `cff' + * modules; see @no-stem-darkening[autofit] and + * @no-stem-darkening[cff]). + * + * * LCD filter weights (@FT_PARAM_TAG_LCD_FILTER_WEIGHTS, corresponding + * to function @FT_Library_SetLcdFilterWeights). + * + * * Seed value for the CFF `random' operator + * (@FT_PARAM_TAG_RANDOM_SEED, corresponding to the `random-seed' + * property provided by the `cff' module; see @random-seed). + * + * Pass NULL as `data' in @FT_Parameter for a given tag to reset the + * option and use the library or module default again. + * + * @input: + * face :: + * A handle to the source face object. + * + * num_properties :: + * The number of properties that follow. + * + * properties :: + * A handle to an @FT_Parameter array with `num_properties' elements. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * Here an example that sets three properties. You must define + * FT_CONFIG_OPTION_SUBPIXEL_RENDERING to make the LCD filter examples + * work. + * + * { + * FT_Parameter property1; + * FT_Bool darken_stems = 1; + * + * FT_Parameter property2; + * FT_LcdFiveTapFilter custom_weight = + * { 0x11, 0x44, 0x56, 0x44, 0x11 }; + * + * FT_Parameter property3; + * FT_Int32 random_seed = 314159265; + * + * FT_Parameter properties[3] = { property1, + * property2, + * property3 }; + * + * + * property1.tag = FT_PARAM_TAG_STEM_DARKENING; + * property1.data = &darken_stems; + * + * property2.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; + * property2.data = custom_weight; + * + * property3.tag = FT_PARAM_TAG_RANDOM_SEED; + * property3.data = &random_seed; + * + * FT_Face_Properties( face, 3, properties ); + * } + * + * The next example resets a single property to its default value. + * + * { + * FT_Parameter property; + * + * + * property.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; + * property.data = NULL; + * + * FT_Face_Properties( face, 1, &property ); + * } + * + */ + FT_EXPORT( FT_Error ) + FT_Face_Properties( FT_Face face, + FT_UInt num_properties, + FT_Parameter* properties ); + + /*************************************************************************/ /* */ /* */ /* FT_Get_Name_Index */ /* */ /* */ - /* Return the glyph index of a given glyph name. This function uses */ - /* driver specific objects to do the translation. */ + /* Return the glyph index of a given glyph name. */ /* */ /* */ /* face :: A handle to the source face object. */ @@ -3610,8 +3800,10 @@ FT_BEGIN_HEADER * FT_SUBGLYPH_FLAG_XXX * * @description: - * A list of constants used to describe subglyphs. Please refer to the - * TrueType specification for the meaning of the various flags. + * A list of constants describing subglyphs. Please refer to the + * `glyf' table description in the OpenType specification for the + * meaning of the various flags (which get synthesized for + * non-OpenType subglyphs). * * @values: * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS :: @@ -3672,7 +3864,7 @@ FT_BEGIN_HEADER * @note: * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be * interpreted depending on the flags returned in `*p_flags'. See the - * TrueType specification for details. + * OpenType specification for details. * */ FT_EXPORT( FT_Error ) @@ -3712,33 +3904,31 @@ FT_BEGIN_HEADER /* the font software copyright owner. */ /* */ /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING :: */ - /* If this bit is set, the font may be embedded and temporarily */ - /* loaded on the remote system. Documents containing Preview & */ - /* Print fonts must be opened `read-only'; no edits can be applied */ - /* to the document. */ + /* The font may be embedded and temporarily loaded on the remote */ + /* system. Documents containing Preview & Print fonts must be */ + /* opened `read-only'; no edits can be applied to the document. */ /* */ /* FT_FSTYPE_EDITABLE_EMBEDDING :: */ - /* If this bit is set, the font may be embedded but must only be */ - /* installed temporarily on other systems. In contrast to Preview */ - /* & Print fonts, documents containing editable fonts may be opened */ - /* for reading, editing is permitted, and changes may be saved. */ + /* The font may be embedded but must only be installed temporarily */ + /* on other systems. In contrast to Preview & Print fonts, */ + /* documents containing editable fonts may be opened for reading, */ + /* editing is permitted, and changes may be saved. */ /* */ /* FT_FSTYPE_NO_SUBSETTING :: */ - /* If this bit is set, the font may not be subsetted prior to */ - /* embedding. */ + /* The font may not be subsetted prior to embedding. */ /* */ /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY :: */ - /* If this bit is set, only bitmaps contained in the font may be */ - /* embedded; no outline data may be embedded. If there are no */ - /* bitmaps available in the font, then the font is unembeddable. */ + /* Only bitmaps contained in the font may be embedded; no outline */ + /* data may be embedded. If there are no bitmaps available in the */ + /* font, then the font is unembeddable. */ /* */ /* */ /* The flags are ORed together, thus more than a single value can be */ /* returned. */ /* */ - /* While the fsType flags can indicate that a font may be embedded, a */ - /* license with the font vendor may be separately required to use the */ - /* font in this way. */ + /* While the `fsType' flags can indicate that a font may be embedded, */ + /* a license with the font vendor may be separately required to use */ + /* the font in this way. */ /* */ #define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000 #define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002 @@ -3754,13 +3944,13 @@ FT_BEGIN_HEADER /* FT_Get_FSType_Flags */ /* */ /* */ - /* Return the fsType flags for a font. */ + /* Return the `fsType' flags for a font. */ /* */ /* */ /* face :: A handle to the source face object. */ /* */ /* */ - /* The fsType flags, @FT_FSTYPE_XXX. */ + /* The `fsType' flags, see @FT_FSTYPE_XXX. */ /* */ /* */ /* Use this function rather than directly reading the `fs_type' field */ @@ -3780,39 +3970,51 @@ FT_BEGIN_HEADER /* glyph_variants */ /* */ /* */ - /* Glyph Variants */ + /* Unicode Variation Sequences */ /* */ /* <Abstract> */ - /* The FreeType~2 interface to Unicode Ideographic Variation */ - /* Sequences (IVS), using the SFNT cmap format~14. */ + /* The FreeType~2 interface to Unicode Variation Sequences (UVS), */ + /* using the SFNT cmap format~14. */ /* */ /* <Description> */ - /* Many CJK characters have variant forms. They are a sort of grey */ - /* area somewhere between being totally irrelevant and semantically */ - /* distinct; for this reason, the Unicode consortium decided to */ - /* introduce Ideographic Variation Sequences (IVS), consisting of a */ - /* Unicode base character and one of 240 variant selectors */ - /* (U+E0100-U+E01EF), instead of further extending the already huge */ - /* code range for CJK characters. */ - /* */ - /* An IVS is registered and unique; for further details please refer */ - /* to Unicode Technical Standard #37, the Ideographic Variation */ - /* Database: */ - /* */ - /* http://www.unicode.org/reports/tr37/ */ - /* */ - /* To date (November 2014), the character with the most variants is */ - /* U+9089, having 32 such IVS. */ - /* */ - /* Adobe and MS decided to support IVS with a new cmap subtable */ - /* (format~14). It is an odd subtable because it is not a mapping of */ - /* input code points to glyphs, but contains lists of all variants */ - /* supported by the font. */ - /* */ - /* A variant may be either `default' or `non-default'. A default */ - /* variant is the one you will get for that code point if you look it */ - /* up in the standard Unicode cmap. A non-default variant is a */ - /* different glyph. */ + /* Many characters, especially for CJK scripts, have variant forms. */ + /* They are a sort of grey area somewhere between being totally */ + /* irrelevant and semantically distinct; for this reason, the Unicode */ + /* consortium decided to introduce Variation Sequences (VS), */ + /* consisting of a Unicode base character and a variation selector */ + /* instead of further extending the already huge number of */ + /* characters. */ + /* */ + /* Unicode maintains two different sets, namely `Standardized */ + /* Variation Sequences' and registered `Ideographic Variation */ + /* Sequences' (IVS), collected in the `Ideographic Variation */ + /* Database' (IVD). */ + /* */ + /* http://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt */ + /* http://unicode.org/reports/tr37/ */ + /* http://unicode.org/ivd/ */ + /* */ + /* To date (January 2017), the character with the most ideographic */ + /* variations is U+9089, having 32 such IVS. */ + /* */ + /* Three Mongolian Variation Selectors have the values U+180B-U+180D; */ + /* 256 generic Variation Selectors are encoded in the ranges */ + /* U+FE00-U+FE0F and U+E0100-U+E01EF. IVS currently use Variation */ + /* Selectors from the range U+E0100-U+E01EF only. */ + /* */ + /* A VS consists of the base character value followed by a single */ + /* Variation Selector. For example, to get the first variation of */ + /* U+9089, you have to write the character sequence `U+9089 U+E0100'. */ + /* */ + /* Adobe and MS decided to support both standardized and ideographic */ + /* VS with a new cmap subtable (format~14). It is an odd subtable */ + /* because it is not a mapping of input code points to glyphs, but */ + /* contains lists of all variations supported by the font. */ + /* */ + /* A variation may be either `default' or `non-default' for a given */ + /* font. A default variation is the one you will get for that code */ + /* point if you look it up in the standard Unicode cmap. A */ + /* non-default variation is a different glyph. */ /* */ /*************************************************************************/ @@ -3868,8 +4070,8 @@ FT_BEGIN_HEADER /* FT_Face_GetCharVariantIsDefault */ /* */ /* <Description> */ - /* Check whether this variant of this Unicode character is the one to */ - /* be found in the `cmap'. */ + /* Check whether this variation of this Unicode character is the one */ + /* to be found in the `cmap'. */ /* */ /* <Input> */ /* face :: */ @@ -3883,7 +4085,7 @@ FT_BEGIN_HEADER /* */ /* <Return> */ /* 1~if found in the standard (Unicode) cmap, 0~if found in the */ - /* variation selector cmap, or -1 if it is not a variant. */ + /* variation selector cmap, or -1 if it is not a variation. */ /* */ /* <Note> */ /* This function is only meaningful if the font has a variation */ @@ -3904,7 +4106,7 @@ FT_BEGIN_HEADER /* FT_Face_GetVariantSelectors */ /* */ /* <Description> */ - /* Return a zero-terminated list of Unicode variant selectors found */ + /* Return a zero-terminated list of Unicode variation selectors found */ /* in the font. */ /* */ /* <Input> */ @@ -3913,7 +4115,7 @@ FT_BEGIN_HEADER /* */ /* <Return> */ /* A pointer to an array of selector code points, or NULL if there is */ - /* no valid variant selector cmap subtable. */ + /* no valid variation selector cmap subtable. */ /* */ /* <Note> */ /* The last item in the array is~0; the array is owned by the */ @@ -3933,7 +4135,7 @@ FT_BEGIN_HEADER /* FT_Face_GetVariantsOfChar */ /* */ /* <Description> */ - /* Return a zero-terminated list of Unicode variant selectors found */ + /* Return a zero-terminated list of Unicode variation selectors found */ /* for the specified character code. */ /* */ /* <Input> */ @@ -3944,7 +4146,7 @@ FT_BEGIN_HEADER /* The character codepoint in Unicode. */ /* */ /* <Return> */ - /* A pointer to an array of variant selector code points that are */ + /* A pointer to an array of variation selector code points that are */ /* active for the given character, or NULL if the corresponding list */ /* is empty. */ /* */ @@ -3968,19 +4170,19 @@ FT_BEGIN_HEADER /* */ /* <Description> */ /* Return a zero-terminated list of Unicode character codes found for */ - /* the specified variant selector. */ + /* the specified variation selector. */ /* */ /* <Input> */ /* face :: */ /* A handle to the source face object. */ /* */ /* variantSelector :: */ - /* The variant selector code point in Unicode. */ + /* The variation selector code point in Unicode. */ /* */ /* <Return> */ /* A list of all the code points that are specified by this selector */ /* (both default and non-default codes are returned) or NULL if there */ - /* is no valid cmap or the variant selector is invalid. */ + /* is no valid cmap or the variation selector is invalid. */ /* */ /* <Note> */ /* The last item in the array is~0; the array is owned by the */ @@ -4030,16 +4232,17 @@ FT_BEGIN_HEADER /* FT_MulDiv */ /* */ /* <Description> */ - /* A very simple function used to perform the computation `(a*b)/c' */ - /* with maximum accuracy (it uses a 64-bit intermediate integer */ - /* whenever necessary). */ + /* Compute `(a*b)/c' with maximum accuracy, using a 64-bit */ + /* intermediate integer whenever necessary. */ /* */ /* This function isn't necessarily as fast as some processor specific */ /* operations, but is at least completely portable. */ /* */ /* <Input> */ /* a :: The first multiplier. */ + /* */ /* b :: The second multiplier. */ + /* */ /* c :: The divisor. */ /* */ /* <Return> */ @@ -4059,12 +4262,12 @@ FT_BEGIN_HEADER /* FT_MulFix */ /* */ /* <Description> */ - /* A very simple function used to perform the computation */ - /* `(a*b)/0x10000' with maximum accuracy. Most of the time this is */ - /* used to multiply a given value by a 16.16 fixed-point factor. */ + /* Compute `(a*b)/0x10000' with maximum accuracy. Its main use is to */ + /* multiply a given value by a 16.16 fixed-point factor. */ /* */ /* <Input> */ /* a :: The first multiplier. */ + /* */ /* b :: The second multiplier. Use a 16.16 factor here whenever */ /* possible (see note below). */ /* */ @@ -4093,12 +4296,12 @@ FT_BEGIN_HEADER /* FT_DivFix */ /* */ /* <Description> */ - /* A very simple function used to perform the computation */ - /* `(a*0x10000)/b' with maximum accuracy. Most of the time, this is */ - /* used to divide a given value by a 16.16 fixed-point factor. */ + /* Compute `(a*0x10000)/b' with maximum accuracy. Its main use is to */ + /* divide a given value by a 16.16 fixed-point factor. */ /* */ /* <Input> */ /* a :: The numerator. */ + /* */ /* b :: The denominator. Use a 16.16 factor here. */ /* */ /* <Return> */ @@ -4115,13 +4318,13 @@ FT_BEGIN_HEADER /* FT_RoundFix */ /* */ /* <Description> */ - /* A very simple function used to round a 16.16 fixed number. */ + /* Round a 16.16 fixed number. */ /* */ /* <Input> */ /* a :: The number to be rounded. */ /* */ /* <Return> */ - /* `a' rounded to nearest 16.16 fixed integer, halfway cases away */ + /* `a' rounded to the nearest 16.16 fixed integer, halfway cases away */ /* from zero. */ /* */ FT_EXPORT( FT_Fixed ) @@ -4134,8 +4337,7 @@ FT_BEGIN_HEADER /* FT_CeilFix */ /* */ /* <Description> */ - /* A very simple function used to compute the ceiling function of a */ - /* 16.16 fixed number. */ + /* Compute the smallest following integer of a 16.16 fixed number. */ /* */ /* <Input> */ /* a :: The number for which the ceiling function is to be computed. */ @@ -4153,8 +4355,7 @@ FT_BEGIN_HEADER /* FT_FloorFix */ /* */ /* <Description> */ - /* A very simple function used to compute the floor function of a */ - /* 16.16 fixed number. */ + /* Compute the largest previous integer of a 16.16 fixed number. */ /* */ /* <Input> */ /* a :: The number for which the floor function is to be computed. */ @@ -4240,8 +4441,8 @@ FT_BEGIN_HEADER * */ #define FREETYPE_MAJOR 2 -#define FREETYPE_MINOR 7 -#define FREETYPE_PATCH 1 +#define FREETYPE_MINOR 8 +#define FREETYPE_PATCH 0 /*************************************************************************/ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftadvanc.h b/Source/ThirdParty/FreeType/include/freetype/ftadvanc.h index 023dd84b7a..dea96e0db4 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftadvanc.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftadvanc.h @@ -4,7 +4,7 @@ /* */ /* Quick computation of advance widths (specification only). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftautoh.h b/Source/ThirdParty/FreeType/include/freetype/ftautoh.h index 48ff1aa26e..abd540f0b5 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftautoh.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftautoh.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for controlling the auto-hinter (specification only). */ /* */ -/* Copyright 2012-2016 by */ +/* Copyright 2012-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -448,7 +448,7 @@ FT_BEGIN_HEADER * no-stem-darkening[autofit] * * @description: - * *Experimental* *only,* *requires* *linear* *alpha* *blending* *and* + * *Experimental* *only*, *requires* *linear* *alpha* *blending* *and* * *gamma* *correction* * * Stem darkening emboldens glyphs at smaller sizes to make them more @@ -477,9 +477,31 @@ FT_BEGIN_HEADER * of emboldening versus the CFF driver. * * This property can be set via the `FREETYPE_PROPERTIES' environment - * variable similar to the CFF driver. + * variable similar to the CFF driver. It can also be set per face + * using @FT_Face_Properties with @FT_PARAM_TAG_STEM_DARKENING. + * + */ + + + /************************************************************************** + * + * @constant: + * FT_PARAM_TAG_STEM_DARKENING + * + * @description: + * An @FT_Parameter tag to be used with @FT_Face_Properties. The + * corresponding Boolean argument specifies whether to apply stem + * darkening, overriding the global default values or the values set up + * with @FT_Property_Set (see @no-stem-darkening[autofit] and + * @no-stem-darkening[cff]). + * + * This is a passive setting that only takes effect if the font driver + * or autohinter honors it, which the CFF driver always does, but the + * autohinter only in `light' hinting mode (as of version 2.7.0). * */ +#define FT_PARAM_TAG_STEM_DARKENING \ + FT_MAKE_TAG( 'd', 'a', 'r', 'k' ) /************************************************************************** diff --git a/Source/ThirdParty/FreeType/include/freetype/ftbbox.h b/Source/ThirdParty/FreeType/include/freetype/ftbbox.h index 2a4d214416..f03bdc1e1e 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftbbox.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftbbox.h @@ -4,7 +4,7 @@ /* */ /* FreeType exact bbox computation (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftbdf.h b/Source/ThirdParty/FreeType/include/freetype/ftbdf.h index 016dba086d..3d3106bad0 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftbdf.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftbdf.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing BDF-specific strings (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftbitmap.h b/Source/ThirdParty/FreeType/include/freetype/ftbitmap.h index 0eac7b9d7d..04b2402ad0 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftbitmap.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftbitmap.h @@ -4,7 +4,7 @@ /* */ /* FreeType utility functions for bitmaps (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftbzip2.h b/Source/ThirdParty/FreeType/include/freetype/ftbzip2.h index b7f2eee87d..9147a790a4 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftbzip2.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftbzip2.h @@ -4,7 +4,7 @@ /* */ /* Bzip2-compressed stream support. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2017 by */ /* Joel Klinghed. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftcache.h b/Source/ThirdParty/FreeType/include/freetype/ftcache.h index 883c88d5d2..5ff3ccf404 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftcache.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftcache.h @@ -4,7 +4,7 @@ /* */ /* FreeType Cache subsystem (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftcffdrv.h b/Source/ThirdParty/FreeType/include/freetype/ftcffdrv.h index 8f88cc48fd..477b6ddb18 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftcffdrv.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftcffdrv.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for controlling the CFF driver (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -113,6 +113,7 @@ FT_BEGIN_HEADER * hinting-engine[cff] * no-stem-darkening[cff] * darkening-parameters[cff] + * random-seed * */ @@ -203,6 +204,8 @@ FT_BEGIN_HEADER * * This property can be set via the `FREETYPE_PROPERTIES' environment * variable (using values 1 and 0 for `on' and `off', respectively). + * It can also be set per face using @FT_Face_Properties with + * @FT_PARAM_TAG_STEM_DARKENING. * */ @@ -263,6 +266,49 @@ FT_BEGIN_HEADER * } */ + + /************************************************************************** + * + * @property: + * random-seed + * + * @description: + * By default, the seed value for the CFF `random' operator is set to a + * random value. However, mainly for debugging purposes, it is often + * necessary to use a known value as a seed so that the pseudo-random + * number sequences generated by `random' are repeatable. + * + * The `random-seed' property does that. Its argument is a signed 32bit + * integer; if the value is zero or negative, the seed given by the + * `intitialRandomSeed' private DICT operator in a CFF file gets used + * (or a default value if there is no such operator). If the value is + * positive, use it instead of `initialRandomSeed', which is + * consequently ignored. + * + * @note: + * This property can be set via the `FREETYPE_PROPERTIES' environment + * variable. It can also be set per face using @FT_Face_Properties with + * @FT_PARAM_TAG_RANDOM_SEED. + * + */ + + + /************************************************************************** + * + * @constant: + * FT_PARAM_TAG_RANDOM_SEED + * + * @description: + * An @FT_Parameter tag to be used with @FT_Face_Properties. The + * corresponding 32bit signed integer argument overrides the CFF + * module's random seed value with a face-specific one; see + * @random-seed. + * + */ +#define FT_PARAM_TAG_RANDOM_SEED \ + FT_MAKE_TAG( 's', 'e', 'e', 'd' ) + + /* */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftchapters.h b/Source/ThirdParty/FreeType/include/freetype/ftchapters.h index ab4389530e..a0a121b0a1 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftchapters.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftchapters.h @@ -77,6 +77,7 @@ /* auto_hinter */ /* cff_driver */ /* tt_driver */ +/* pcf_driver */ /* */ /***************************************************************************/ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftcid.h b/Source/ThirdParty/FreeType/include/freetype/ftcid.h index e1bc9fe015..4adcbeeda9 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftcid.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftcid.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing CID font information (specification). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* Dereg Clegg and Michael Toftdal. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/fterrdef.h b/Source/ThirdParty/FreeType/include/freetype/fterrdef.h index 3f53dd5820..cabbac8273 100644 --- a/Source/ThirdParty/FreeType/include/freetype/fterrdef.h +++ b/Source/ThirdParty/FreeType/include/freetype/fterrdef.h @@ -4,7 +4,7 @@ /* */ /* FreeType error codes (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -231,6 +231,8 @@ "invalid PostScript (post) table format" ) FT_ERRORDEF_( Invalid_Post_Table, 0x9B, "invalid PostScript (post) table" ) + FT_ERRORDEF_( DEF_In_Glyf_Bytecode, 0x9C, + "found FDEF or IDEF opcode in glyf bytecode" ) /* CFF, CID, and Type 1 errors */ diff --git a/Source/ThirdParty/FreeType/include/freetype/fterrors.h b/Source/ThirdParty/FreeType/include/freetype/fterrors.h index e15bfb001e..42769fa7bf 100644 --- a/Source/ThirdParty/FreeType/include/freetype/fterrors.h +++ b/Source/ThirdParty/FreeType/include/freetype/fterrors.h @@ -4,7 +4,7 @@ /* */ /* FreeType error code handling (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -106,7 +106,7 @@ /* */ /* #undefine __FTERRORS_H__ */ /* */ - /* work for backwards compatibility. */ + /* work for backward compatibility. */ /* */ #if !( defined( FTERRORS_H_ ) && defined ( __FTERRORS_H__ ) ) #define FTERRORS_H_ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftfntfmt.h b/Source/ThirdParty/FreeType/include/freetype/ftfntfmt.h index bd423247bb..337758328a 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftfntfmt.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftfntfmt.h @@ -4,7 +4,7 @@ /* */ /* Support functions for font formats. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftgasp.h b/Source/ThirdParty/FreeType/include/freetype/ftgasp.h index 3f5b3bc695..ce18d64784 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftgasp.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftgasp.h @@ -4,7 +4,7 @@ /* */ /* Access of TrueType's `gasp' table (specification). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -92,8 +92,8 @@ #define FT_GASP_NO_TABLE -1 #define FT_GASP_DO_GRIDFIT 0x01 #define FT_GASP_DO_GRAY 0x02 +#define FT_GASP_SYMMETRIC_GRIDFIT 0x04 #define FT_GASP_SYMMETRIC_SMOOTHING 0x08 -#define FT_GASP_SYMMETRIC_GRIDFIT 0x10 /************************************************************************* @@ -102,17 +102,25 @@ * FT_Get_Gasp * * @description: - * Read the `gasp' table from a TrueType or OpenType font file and - * return the entry corresponding to a given character pixel size. + * For a TrueType or OpenType font file, return the rasterizer behaviour + * flags from the font's `gasp' table corresponding to a given + * character pixel size. * * @input: * face :: The source face handle. + * * ppem :: The vertical character pixel size. * * @return: * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no * `gasp' table in the face. * + * @note: + * If you want to use the MM functionality of OpenType variation fonts + * (i.e., using @FT_Set_Var_Design_Coordinates and friends), call this + * function *after* setting an instance since the return values can + * change. + * * @since: * 2.3.0 */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftglyph.h b/Source/ThirdParty/FreeType/include/freetype/ftglyph.h index d9840a81fc..79879a7ac7 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftglyph.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftglyph.h @@ -4,7 +4,7 @@ /* */ /* FreeType convenience functions to handle glyphs (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -453,7 +453,7 @@ FT_BEGIN_HEADER /* */ /* */ /* // load glyph */ - /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ + /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAULT ); */ /* */ /* // extract glyph image */ /* error = FT_Get_Glyph( face->glyph, &glyph ); */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftgxval.h b/Source/ThirdParty/FreeType/include/freetype/ftgxval.h index a58e86a040..f239c71eb1 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftgxval.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftgxval.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for validating TrueTypeGX/AAT tables (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Masatake YAMATO, Redhat K.K, */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftgzip.h b/Source/ThirdParty/FreeType/include/freetype/ftgzip.h index 3932ce6887..bd5ceaab9f 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftgzip.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftgzip.h @@ -4,7 +4,7 @@ /* */ /* Gzip-compressed stream support. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftimage.h b/Source/ThirdParty/FreeType/include/freetype/ftimage.h index 7b461550cc..1a049ef16d 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftimage.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftimage.h @@ -5,7 +5,7 @@ /* FreeType glyph image formats and default raster interface */ /* (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -619,7 +619,7 @@ FT_BEGIN_HEADER /* */ /* { */ /* x' = (x << shift) - delta */ - /* y' = (x << shift) - delta */ + /* y' = (y << shift) - delta */ /* } */ /* */ /* Set the values of `shift' and `delta' to~0 to get the original */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftincrem.h b/Source/ThirdParty/FreeType/include/freetype/ftincrem.h index 46b58b7917..f6ae2baed6 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftincrem.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftincrem.h @@ -4,7 +4,7 @@ /* */ /* FreeType incremental loading (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftlcdfil.h b/Source/ThirdParty/FreeType/include/freetype/ftlcdfil.h index e06a8957f5..680bd90c89 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftlcdfil.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftlcdfil.h @@ -5,7 +5,7 @@ /* FreeType API for color filtering of subpixel bitmap glyphs */ /* (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -268,6 +268,9 @@ FT_BEGIN_HEADER * defined in your build of the library, which should correspond to all * default builds of FreeType. * + * LCD filter weights can also be set per face using @FT_Face_Properties + * with @FT_PARAM_TAG_LCD_FILTER_WEIGHTS. + * * @since: * 2.4.0 */ @@ -275,6 +278,38 @@ FT_BEGIN_HEADER FT_Library_SetLcdFilterWeights( FT_Library library, unsigned char *weights ); + + /************************************************************************** + * + * @constant: + * FT_PARAM_TAG_LCD_FILTER_WEIGHTS + * + * @description: + * An @FT_Parameter tag to be used with @FT_Face_Properties. The + * corresponding argument specifies the five LCD filter weights for a + * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding + * the global default values or the values set up with + * @FT_Library_SetLcdFilterWeights. + * + */ +#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \ + FT_MAKE_TAG( 'l', 'c', 'd', 'f' ) + + + /* + * @type: + * FT_LcdFiveTapFilter + * + * @description: + * A typedef for passing the five LCD filter weights to + * @FT_Face_Properties within an @FT_Parameter structure. + * + */ +#define FT_LCD_FILTER_FIVE_TAPS 5 + + typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS]; + + /* */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftlist.h b/Source/ThirdParty/FreeType/include/freetype/ftlist.h index 82f437ac61..5309cb18ba 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftlist.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftlist.h @@ -4,7 +4,7 @@ /* */ /* Generic list support for FreeType (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftlzw.h b/Source/ThirdParty/FreeType/include/freetype/ftlzw.h index 582e2c1465..a82c95e7c9 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftlzw.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftlzw.h @@ -4,7 +4,7 @@ /* */ /* LZW-compressed stream support. */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftmac.h b/Source/ThirdParty/FreeType/include/freetype/ftmac.h index adb15cadf3..ad97c6e4c3 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftmac.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftmac.h @@ -4,7 +4,7 @@ /* */ /* Additional Mac-specific API. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftmm.h b/Source/ThirdParty/FreeType/include/freetype/ftmm.h index a0238c5d29..c41b80ea67 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftmm.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftmm.h @@ -4,7 +4,7 @@ /* */ /* FreeType Multiple Master font interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -43,11 +43,10 @@ FT_BEGIN_HEADER /* Master fonts, i.e., the selection of specific design instances by */ /* setting design axis coordinates. */ /* */ - /* George Williams has extended this interface to make it work with */ - /* both Type~1 Multiple Masters fonts and GX distortable (var) */ - /* fonts. Some of these routines only work with MM fonts, others */ - /* will work with both types. They are similar enough that a */ - /* consistent interface makes sense. */ + /* Besides Adobe MM fonts, the interface supports Apple's TrueType GX */ + /* and OpenType variation fonts. Some of the routines only work with */ + /* Adobe MM fonts, others will work with all three types. They are */ + /* similar enough that a consistent interface makes sense. */ /* */ /*************************************************************************/ @@ -58,10 +57,11 @@ FT_BEGIN_HEADER /* FT_MM_Axis */ /* */ /* <Description> */ - /* A simple structure used to model a given axis in design space for */ - /* Multiple Masters fonts. */ + /* A structure to model a given axis in design space for Multiple */ + /* Masters fonts. */ /* */ - /* This structure can't be used for GX var fonts. */ + /* This structure can't be used for TrueType GX or OpenType variation */ + /* fonts. */ /* */ /* <Fields> */ /* name :: The axis's name. */ @@ -85,10 +85,11 @@ FT_BEGIN_HEADER /* FT_Multi_Master */ /* */ /* <Description> */ - /* A structure used to model the axes and space of a Multiple Masters */ + /* A structure to model the axes and space of a Multiple Masters */ /* font. */ /* */ - /* This structure can't be used for GX var fonts. */ + /* This structure can't be used for TrueType GX or OpenType variation */ + /* fonts. */ /* */ /* <Fields> */ /* num_axis :: Number of axes. Cannot exceed~4. */ @@ -115,27 +116,35 @@ FT_BEGIN_HEADER /* FT_Var_Axis */ /* */ /* <Description> */ - /* A simple structure used to model a given axis in design space for */ - /* Multiple Masters and GX var fonts. */ + /* A structure to model a given axis in design space for Multiple */ + /* Masters, TrueType GX, and OpenType variation fonts. */ /* */ /* <Fields> */ /* name :: The axis's name. */ - /* Not always meaningful for GX. */ + /* Not always meaningful for TrueType GX or OpenType */ + /* variation fonts. */ /* */ /* minimum :: The axis's minimum design coordinate. */ /* */ /* def :: The axis's default design coordinate. */ - /* FreeType computes meaningful default values for MM; it */ - /* is then an integer value, not in 16.16 format. */ + /* FreeType computes meaningful default values for Adobe */ + /* MM fonts. */ /* */ /* maximum :: The axis's maximum design coordinate. */ /* */ - /* tag :: The axis's tag (the GX equivalent to `name'). */ - /* FreeType provides default values for MM if possible. */ + /* tag :: The axis's tag (the equivalent to `name' for TrueType */ + /* GX and OpenType variation fonts). FreeType provides */ + /* default values for Adobe MM fonts if possible. */ /* */ - /* strid :: The entry in `name' table (another GX version of */ - /* `name'). */ - /* Not meaningful for MM. */ + /* strid :: The axis name entry in the font's `name' table. This */ + /* is another (and often better) version of the `name' */ + /* field for TrueType GX or OpenType variation fonts. Not */ + /* meaningful for Adobe MM fonts. */ + /* */ + /* <Note> */ + /* The fields `minimum', `def', and `maximum' are 16.16 fractional */ + /* values for TrueType GX and OpenType variation fonts. For Adobe MM */ + /* fonts, the values are integers. */ /* */ typedef struct FT_Var_Axis_ { @@ -157,15 +166,19 @@ FT_BEGIN_HEADER /* FT_Var_Named_Style */ /* */ /* <Description> */ - /* A simple structure used to model a named style in a GX var font. */ + /* A structure to model a named instance in a TrueType GX or OpenType */ + /* variation font. */ /* */ - /* This structure can't be used for MM fonts. */ + /* This structure can't be used for Adobe MM fonts. */ /* */ /* <Fields> */ - /* coords :: The design coordinates for this style. */ + /* coords :: The design coordinates for this instance. */ /* This is an array with one entry for each axis. */ /* */ - /* strid :: The entry in `name' table identifying this style. */ + /* strid :: The entry in `name' table identifying this instance. */ + /* */ + /* psid :: The entry in `name' table identifying a PostScript name */ + /* for this instance. */ /* */ typedef struct FT_Var_Named_Style_ { @@ -182,17 +195,19 @@ FT_BEGIN_HEADER /* FT_MM_Var */ /* */ /* <Description> */ - /* A structure used to model the axes and space of a Multiple Masters */ - /* or GX var distortable font. */ + /* A structure to model the axes and space of a Adobe MM, TrueType */ + /* GX, or OpenType variation font. */ /* */ - /* Some fields are specific to one format and not to the other. */ + /* Some fields are specific to one format and not to the others. */ /* */ /* <Fields> */ /* num_axis :: The number of axes. The maximum value is~4 for */ - /* MM; no limit in GX. */ + /* Adobe MM fonts; no limit in TrueType GX or */ + /* OpenType variation fonts. */ /* */ /* num_designs :: The number of designs; should be normally */ - /* 2^num_axis for MM fonts. Not meaningful for GX */ + /* 2^num_axis for Adobe MM fonts. Not meaningful */ + /* for TrueType GX or OpenType variation fonts */ /* (where every glyph could have a different */ /* number of designs). */ /* */ @@ -200,21 +215,23 @@ FT_BEGIN_HEADER /* a tuple of design coordinates that has a string */ /* ID (in the `name' table) associated with it. */ /* The font can tell the user that, for example, */ - /* [Weight=1.5,Width=1.1] is `Bold'. */ + /* [Weight=1.5,Width=1.1] is `Bold'. Another name */ + /* for `named style' is `named instance'. */ /* */ - /* For Type 1 Multiple Masters fonts, this value */ - /* is always zero because the format does not */ - /* support named styles. */ + /* For Adobe Multiple Masters fonts, this value is */ + /* always zero because the format does not support */ + /* named styles. */ /* */ /* axis :: An axis descriptor table. */ - /* GX fonts contain slightly more data than MM. */ + /* TrueType GX and OpenType variation fonts */ + /* contain slightly more data than Adobe MM fonts. */ /* Memory management of this pointer is done */ /* internally by FreeType. */ /* */ - /* namedstyle :: A named style table. */ - /* Only meaningful with GX. */ - /* Memory management of this pointer is done */ - /* internally by FreeType. */ + /* namedstyle :: A named style (instance) table. */ + /* Only meaningful for TrueType GX and OpenType */ + /* variation fonts. Memory management of this */ + /* pointer is done internally by FreeType. */ /* */ typedef struct FT_MM_Var_ { @@ -233,9 +250,10 @@ FT_BEGIN_HEADER /* FT_Get_Multi_Master */ /* */ /* <Description> */ - /* Retrieve the Multiple Master descriptor of a given font. */ + /* Retrieve a variation descriptor of a given Adobe MM font. */ /* */ - /* This function can't be used with GX fonts. */ + /* This function can't be used with TrueType GX or OpenType variation */ + /* fonts. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ @@ -257,13 +275,15 @@ FT_BEGIN_HEADER /* FT_Get_MM_Var */ /* */ /* <Description> */ - /* Retrieve the Multiple Master/GX var descriptor of a given font. */ + /* Retrieve a variation descriptor for a given font. */ + /* */ + /* This function works with all supported variation formats. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ /* */ /* <Output> */ - /* amaster :: The Multiple Masters/GX var descriptor. */ + /* amaster :: The variation descriptor. */ /* Allocates a data structure, which the user must */ /* deallocate with `free' after use. */ /* */ @@ -281,10 +301,11 @@ FT_BEGIN_HEADER /* FT_Set_MM_Design_Coordinates */ /* */ /* <Description> */ - /* For Multiple Masters fonts, choose an interpolated font design */ - /* through design coordinates. */ + /* For Adobe MM fonts, choose an interpolated font design through */ + /* design coordinates. */ /* */ - /* This function can't be used with GX fonts. */ + /* This function can't be used with TrueType GX or OpenType variation */ + /* fonts. */ /* */ /* <InOut> */ /* face :: A handle to the source face. */ @@ -312,8 +333,9 @@ FT_BEGIN_HEADER /* FT_Set_Var_Design_Coordinates */ /* */ /* <Description> */ - /* For Multiple Master or GX Var fonts, choose an interpolated font */ - /* design through design coordinates. */ + /* Choose an interpolated font design through design coordinates. */ + /* */ + /* This function works with all supported variation formats. */ /* */ /* <InOut> */ /* face :: A handle to the source face. */ @@ -341,8 +363,10 @@ FT_BEGIN_HEADER /* FT_Get_Var_Design_Coordinates */ /* */ /* <Description> */ - /* For Multiple Master and GX Var fonts, get the design coordinates */ - /* of the currently selected interpolated font. */ + /* Get the design coordinates of the currently selected interpolated */ + /* font. */ + /* */ + /* This function works with all supported variation formats. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ @@ -369,8 +393,10 @@ FT_BEGIN_HEADER /* FT_Set_MM_Blend_Coordinates */ /* */ /* <Description> */ - /* For Multiple Masters and GX var fonts, choose an interpolated font */ - /* design through normalized blend coordinates. */ + /* Choose an interpolated font design through normalized blend */ + /* coordinates. */ + /* */ + /* This function works with all supported variation formats. */ /* */ /* <InOut> */ /* face :: A handle to the source face. */ @@ -382,8 +408,9 @@ FT_BEGIN_HEADER /* use default values for the remaining axes. */ /* */ /* coords :: The design coordinates array (each element must be */ - /* between 0 and 1.0 for MM fonts, and between -1.0 and */ - /* 1.0 for GX var fonts). */ + /* between 0 and 1.0 for Adobe MM fonts, and between */ + /* -1.0 and 1.0 for TrueType GX and OpenType variation */ + /* fonts). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ @@ -400,16 +427,18 @@ FT_BEGIN_HEADER /* FT_Get_MM_Blend_Coordinates */ /* */ /* <Description> */ - /* For Multiple Masters and GX var fonts, get the normalized blend */ - /* coordinates of the currently selected interpolated font. */ + /* Get the normalized blend coordinates of the currently selected */ + /* interpolated font. */ + /* */ + /* This function works with all supported variation formats. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ /* */ /* num_coords :: The number of normalized blend coordinates to */ /* retrieve. If it is larger than the number of axes, */ - /* set the excess values to~0.5 for MM fonts, and to~0 */ - /* for GX var fonts. */ + /* set the excess values to~0.5 for Adobe MM fonts, and */ + /* to~0 for TrueType GX and OpenType variation fonts. */ /* */ /* <Output> */ /* coords :: The normalized blend coordinates array. */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftmodapi.h b/Source/ThirdParty/FreeType/include/freetype/ftmodapi.h index b4d2758efa..4147aadf8b 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftmodapi.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftmodapi.h @@ -4,7 +4,7 @@ /* */ /* FreeType modules public interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -89,6 +89,7 @@ FT_BEGIN_HEADER /* */ /* FT_Property_Set */ /* FT_Property_Get */ + /* FT_Set_Default_Properties */ /* */ /* FT_New_Library */ /* FT_Done_Library */ @@ -437,6 +438,47 @@ FT_BEGIN_HEADER void* value ); + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Default_Properties */ + /* */ + /* <Description> */ + /* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */ + /* set, this function reads the `FREETYPE_PROPERTIES' environment */ + /* variable to control driver properties. See sections @auto_hinter, */ + /* @cff_driver, @pcf_driver, and @tt_driver for more. */ + /* */ + /* If the compilation option is not set, this function does nothing. */ + /* */ + /* `FREETYPE_PROPERTIES' has the following syntax form (broken here */ + /* into multiple lines for better readability). */ + /* */ + /* { */ + /* <optional whitespace> */ + /* <module-name1> ':' */ + /* <property-name1> '=' <property-value1> */ + /* <whitespace> */ + /* <module-name2> ':' */ + /* <property-name2> '=' <property-value2> */ + /* ... */ + /* } */ + /* */ + /* Example: */ + /* */ + /* { */ + /* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ */ + /* cff:no-stem-darkening=1 \ */ + /* autofitter:warping=1 */ + /* } */ + /* */ + /* <InOut> */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT( void ) + FT_Set_Default_Properties( FT_Library library ); + + /*************************************************************************/ /* */ /* <Function> */ @@ -477,8 +519,9 @@ FT_BEGIN_HEADER /* valid for the life of the @FT_Library object. */ /* */ /* Normally, you would call this function (followed by a call to */ - /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module) */ - /* instead of @FT_Init_FreeType to initialize the FreeType library. */ + /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module, */ + /* and a call to @FT_Set_Default_Properties) instead of */ + /* @FT_Init_FreeType to initialize the FreeType library. */ /* */ /* Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a */ /* library instance. */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftmoderr.h b/Source/ThirdParty/FreeType/include/freetype/ftmoderr.h index 2a7671c816..7f608375e8 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftmoderr.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftmoderr.h @@ -4,7 +4,7 @@ /* */ /* FreeType module error offsets (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftotval.h b/Source/ThirdParty/FreeType/include/freetype/ftotval.h index 3e6e18d8a6..b5d27cfe74 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftotval.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftotval.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for validating OpenType tables (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftoutln.h b/Source/ThirdParty/FreeType/include/freetype/ftoutln.h index ef66d48c8d..07f73ebb1b 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftoutln.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftoutln.h @@ -5,7 +5,7 @@ /* Support for the FT_Outline type used to store glyph shapes of */ /* most scalable font formats (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftpcfdrv.h b/Source/ThirdParty/FreeType/include/freetype/ftpcfdrv.h new file mode 100644 index 0000000000..6622c936fb --- /dev/null +++ b/Source/ThirdParty/FreeType/include/freetype/ftpcfdrv.h @@ -0,0 +1,105 @@ +/***************************************************************************/ +/* */ +/* ftpcfdrv.h */ +/* */ +/* FreeType API for controlling the PCF driver (specification only). */ +/* */ +/* Copyright 2017 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTPCFDRV_H_ +#define FTPCFDRV_H_ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @section: + * pcf_driver + * + * @title: + * The PCF driver + * + * @abstract: + * Controlling the PCF driver module. + * + * @description: + * While FreeType's PCF driver doesn't expose API functions by itself, + * it is possible to control its behaviour with @FT_Property_Set and + * @FT_Property_Get. Right now, there is a single property + * `no-long-family-names' available if FreeType is compiled with + * PCF_CONFIG_OPTION_LONG_FAMILY_NAMES. + * + * The PCF driver's module name is `pcf'. + * + */ + + + /************************************************************************** + * + * @property: + * no-long-family-names + * + * @description: + * If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling + * FreeType, the PCF driver constructs long family names. + * + * There are many PCF fonts just called `Fixed' which look completely + * different, and which have nothing to do with each other. When + * selecting `Fixed' in KDE or Gnome one gets results that appear rather + * random, the style changes often if one changes the size and one + * cannot select some fonts at all. The improve this situation, the PCF + * module prepends the foundry name (plus a space) to the family name. + * It also checks whether there are `wide' characters; all put together, + * family names like `Sony Fixed' or `Misc Fixed Wide' are constructed. + * + * If `no-long-family-names' is set, this feature gets switched off. + * + * { + * FT_Library library; + * FT_Bool no_long_family_names = TRUE; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "pcf", + * "no-long-family-names", + * &no_long_family_names ); + * } + * + * @note: + * This property can be used with @FT_Property_Get also. + * + * This property can be set via the `FREETYPE_PROPERTIES' environment + * variable (using values 1 and 0 for `on' and `off', respectively). + * + */ + + +FT_END_HEADER + + +#endif /* FTPCFDRV_H_ */ + + +/* END */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftpfr.h b/Source/ThirdParty/FreeType/include/freetype/ftpfr.h index 2e1bff2f67..f2a6ae9349 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftpfr.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftpfr.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing PFR-specific data (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftrender.h b/Source/ThirdParty/FreeType/include/freetype/ftrender.h index 278d24a310..960837580a 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftrender.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftrender.h @@ -4,7 +4,7 @@ /* */ /* FreeType renderer modules public interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftsizes.h b/Source/ThirdParty/FreeType/include/freetype/ftsizes.h index 55e0d5ccfd..2f3958a857 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftsizes.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftsizes.h @@ -4,7 +4,7 @@ /* */ /* FreeType size objects management (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftsnames.h b/Source/ThirdParty/FreeType/include/freetype/ftsnames.h index a7b51c2cba..a316540576 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftsnames.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftsnames.h @@ -2,12 +2,12 @@ /* */ /* ftsnames.h */ /* */ -/* Simple interface to access SFNT name tables (which are used */ +/* Simple interface to access SFNT `name' tables (which are used */ /* to hold font names, copyright info, notices, etc.) (specification). */ /* */ /* This is _not_ used to retrieve glyph names! */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -49,7 +49,7 @@ FT_BEGIN_HEADER /* */ /* <Description> */ /* The TrueType and OpenType specifications allow the inclusion of */ - /* a special `names table' in font files. This table contains */ + /* a special names table (`name') in font files. This table contains */ /* textual (and internationalized) information regarding the font, */ /* like family name, copyright, version, etc. */ /* */ @@ -70,30 +70,37 @@ FT_BEGIN_HEADER /* */ /* <Fields> */ /* platform_id :: The platform ID for `string'. */ + /* See @TT_PLATFORM_XXX for possible values. */ /* */ /* encoding_id :: The encoding ID for `string'. */ + /* See @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */ + /* @TT_ISO_ID_XXX, @TT_MS_ID_XXX, and @TT_ADOBE_ID_XXX */ + /* for possible values. */ /* */ /* language_id :: The language ID for `string'. */ + /* See @TT_MAC_LANGID_XXX and @TT_MS_LANGID_XXX for */ + /* possible values. */ + /* */ + /* Registered OpenType values for `language_id' are */ + /* always smaller than 0x8000; values equal or larger */ + /* than 0x8000 usually indicate a language tag string */ + /* (introduced in OpenType version 1.6). Use function */ + /* @FT_Get_Sfnt_LangTag with `language_id' as its */ + /* argument to retrieve the associated language tag. */ /* */ /* name_id :: An identifier for `string'. */ + /* See @TT_NAME_ID_XXX for possible values. */ /* */ /* string :: The `name' string. Note that its format differs */ - /* depending on the (platform,encoding) pair. It can */ - /* be a Pascal String, a UTF-16 one, etc. */ - /* */ - /* Generally speaking, the string is not */ - /* zero-terminated. Please refer to the TrueType */ - /* specification for details. */ + /* depending on the (platform,encoding) pair, being */ + /* either a string of bytes (without a terminating */ + /* NULL byte) or containing UTF-16BE entities. */ /* */ /* string_len :: The length of `string' in bytes. */ /* */ /* <Note> */ - /* Possible values for `platform_id', `encoding_id', `language_id', */ - /* and `name_id' are given in the file `ttnameid.h'. For details */ - /* please refer to the TrueType or OpenType specification. */ - /* */ - /* See also @TT_PLATFORM_XXX, @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */ - /* @TT_ISO_ID_XXX, and @TT_MS_ID_XXX. */ + /* Please refer to the TrueType or OpenType specification for more */ + /* details. */ /* */ typedef struct FT_SfntName_ { @@ -103,7 +110,7 @@ FT_BEGIN_HEADER FT_UShort name_id; FT_Byte* string; /* this string is *not* null-terminated! */ - FT_UInt string_len; /* in bytes */ + FT_UInt string_len; /* in bytes */ } FT_SfntName; @@ -147,47 +154,127 @@ FT_BEGIN_HEADER /* */ /* <Note> */ /* The `string' array returned in the `aname' structure is not */ - /* null-terminated. The application should deallocate it if it is no */ - /* longer in use. */ + /* null-terminated. Note that you don't have to deallocate `string' */ + /* by yourself; FreeType takes care of it if you call @FT_Done_Face. */ /* */ /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */ /* `name' table entries, then do a loop until you get the right */ /* platform, encoding, and name ID. */ /* */ + /* `name' table format~1 entries can use language tags also, see */ + /* @FT_Get_Sfnt_LangTag. */ + /* */ FT_EXPORT( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, FT_UInt idx, FT_SfntName *aname ); + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SfntLangTag */ + /* */ + /* <Description> */ + /* A structure to model a language tag entry from an SFNT `name' */ + /* table. */ + /* */ + /* <Fields> */ + /* string :: The language tag string, encoded in UTF-16BE */ + /* (without trailing NULL bytes). */ + /* */ + /* string_len :: The length of `string' in *bytes*. */ + /* */ + /* <Note> */ + /* Please refer to the TrueType or OpenType specification for more */ + /* details. */ + /* */ + typedef struct FT_SfntLangTag_ + { + FT_Byte* string; /* this string is *not* null-terminated! */ + FT_UInt string_len; /* in bytes */ + + } FT_SfntLangTag; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_LangTag */ + /* */ + /* <Description> */ + /* Retrieve the language tag associated with a language ID of an SFNT */ + /* `name' table entry. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* langID :: The language ID, as returned by @FT_Get_Sfnt_Name. */ + /* This is always a value larger than 0x8000. */ + /* */ + /* <Output> */ + /* alangTag :: The language tag associated with the `name' table */ + /* entry's language ID. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The `string' array returned in the `alangTag' structure is not */ + /* null-terminated. Note that you don't have to deallocate `string' */ + /* by yourself; FreeType takes care of it if you call @FT_Done_Face. */ + /* */ + /* Only `name' table format~1 supports language tags. For format~0 */ + /* tables, this function always returns FT_Err_Invalid_Table. For */ + /* invalid format~1 language ID values, FT_Err_Invalid_Argument is */ + /* returned. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Sfnt_LangTag( FT_Face face, + FT_UInt langID, + FT_SfntLangTag *alangTag ); + + /*************************************************************************** * * @constant: - * FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY + * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY * * @description: - * A constant used as the tag of @FT_Parameter structures to make - * FT_Open_Face() ignore preferred family subfamily names in `name' - * table since OpenType version 1.4. For backwards compatibility with - * legacy systems that have a 4-face-per-family restriction. + * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic + * family names in the `name' table (introduced in OpenType version + * 1.4). Use this for backward compatibility with legacy systems that + * have a four-faces-per-family restriction. * */ -#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY FT_MAKE_TAG( 'i', 'g', 'p', 'f' ) +#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \ + FT_MAKE_TAG( 'i', 'g', 'p', 'f' ) + + + /* this constant is deprecated */ +#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \ + FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY /*************************************************************************** * * @constant: - * FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY + * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY * * @description: - * A constant used as the tag of @FT_Parameter structures to make - * FT_Open_Face() ignore preferred subfamily names in `name' table since - * OpenType version 1.4. For backwards compatibility with legacy - * systems that have a 4-face-per-family restriction. + * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic + * subfamily names in the `name' table (introduced in OpenType version + * 1.4). Use this for backward compatibility with legacy systems that + * have a four-faces-per-family restriction. * */ -#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY FT_MAKE_TAG( 'i', 'g', 'p', 's' ) +#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \ + FT_MAKE_TAG( 'i', 'g', 'p', 's' ) + + + /* this constant is deprecated */ +#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \ + FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY /* */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftstroke.h b/Source/ThirdParty/FreeType/include/freetype/ftstroke.h index b3b9922dad..4a20667c5e 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftstroke.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftstroke.h @@ -4,7 +4,7 @@ /* */ /* FreeType path stroker (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -136,7 +136,7 @@ FT_BEGIN_HEADER * FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line * join as used in XPS. FT_STROKER_LINEJOIN_MITER is an alias * for FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for - * backwards compatibility. + * backward compatibility. */ typedef enum FT_Stroker_LineJoin_ { diff --git a/Source/ThirdParty/FreeType/include/freetype/ftsynth.h b/Source/ThirdParty/FreeType/include/freetype/ftsynth.h index fdfcb6912b..1863fa2383 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftsynth.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftsynth.h @@ -5,7 +5,7 @@ /* FreeType synthesizing code for emboldening and slanting */ /* (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftsystem.h b/Source/ThirdParty/FreeType/include/freetype/ftsystem.h index a75f958022..1aa4762ad6 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftsystem.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftsystem.h @@ -4,7 +4,7 @@ /* */ /* FreeType low-level system interface definition (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/fttrigon.h b/Source/ThirdParty/FreeType/include/freetype/fttrigon.h index f789b524cb..89f0350675 100644 --- a/Source/ThirdParty/FreeType/include/freetype/fttrigon.h +++ b/Source/ThirdParty/FreeType/include/freetype/fttrigon.h @@ -4,7 +4,7 @@ /* */ /* FreeType trigonometric functions (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftttdrv.h b/Source/ThirdParty/FreeType/include/freetype/ftttdrv.h index 22186ee4a5..26bc5e966a 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftttdrv.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftttdrv.h @@ -5,7 +5,7 @@ /* FreeType API for controlling the TrueType driver */ /* (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -110,7 +110,7 @@ FT_BEGIN_HEADER * TrueType interpreter fully allows the advance width to be adjusted in * this mode, just the DWrite client will ignore those changes. * - * _ClearType_ _Backwards_ _Compatibility_ + * _ClearType_ _Backward_ _Compatibility_ * * This is a set of exceptions made in the TrueType interpreter to * minimize hinting techniques that were problematic with the extra @@ -118,9 +118,9 @@ FT_BEGIN_HEADER * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and * http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx. * This technique is not to be confused with ClearType compatible - * widths. ClearType backwards compatibility has no direct impact on + * widths. ClearType backward compatibility has no direct impact on * changing advance widths, but there might be an indirect impact on - * disabling some deltas. This could be worked around in backwards + * disabling some deltas. This could be worked around in backward * compatibility mode. * * _Native_ _ClearType_ _Mode_ @@ -138,7 +138,6 @@ FT_BEGIN_HEADER * interpreter-version * * @description: - * Currently, three versions are available, two representing the * bytecode interpreter with subpixel hinting support (old `Infinality' * code and new stripped-down and higher performance `minimal' code) and @@ -226,7 +225,7 @@ FT_BEGIN_HEADER * filtering. * * If FreeType has not been compiled with the configuration option - * FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes + * TT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes * an `FT_Err_Unimplemented_Feature' error. * * Depending on the graphics framework, Microsoft uses different diff --git a/Source/ThirdParty/FreeType/include/freetype/fttypes.h b/Source/ThirdParty/FreeType/include/freetype/fttypes.h index 2673e79c3c..eab8adaad4 100644 --- a/Source/ThirdParty/FreeType/include/freetype/fttypes.h +++ b/Source/ThirdParty/FreeType/include/freetype/fttypes.h @@ -4,7 +4,7 @@ /* */ /* FreeType simple types definitions (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftwinfnt.h b/Source/ThirdParty/FreeType/include/freetype/ftwinfnt.h index a1a715baa1..1eeef6c8ba 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ftwinfnt.h +++ b/Source/ThirdParty/FreeType/include/freetype/ftwinfnt.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing Windows fnt-specific data. */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ftxf86.h b/Source/ThirdParty/FreeType/include/freetype/ftxf86.h deleted file mode 100644 index 493cccdd0a..0000000000 --- a/Source/ThirdParty/FreeType/include/freetype/ftxf86.h +++ /dev/null @@ -1,83 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftxf86.h */ -/* */ -/* Support functions for X11. */ -/* */ -/* Copyright 2002-2004, 2006, 2007, 2013 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTXF86_H__ -#define __FTXF86_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* font_formats */ - /* */ - /* <Title> */ - /* Font Formats */ - /* */ - /* <Abstract> */ - /* Getting the font format. */ - /* */ - /* <Description> */ - /* The single function in this section can be used to get the font */ - /* format. Note that this information is not needed normally; */ - /* however, there are special cases (like in PDF devices) where it is */ - /* important to differentiate, in spite of FreeType's uniform API. */ - /* */ - /* This function is in the X11/xf86 namespace for historical reasons */ - /* and in no way depends on that windowing system. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_X11_Font_Format */ - /* */ - /* <Description> */ - /* Return a string describing the format of a given face, using values */ - /* that can be used as an X11 FONT_PROPERTY. Possible values are */ - /* `TrueType', `Type~1', `BDF', `PCF', `Type~42', `CID~Type~1', `CFF', */ - /* `PFR', and `Windows~FNT'. */ - /* */ - /* <Input> */ - /* face :: */ - /* Input face handle. */ - /* */ - /* <Return> */ - /* Font format string. NULL in case of error. */ - /* */ - FT_EXPORT( const char* ) - FT_Get_X11_Font_Format( FT_Face face ); - - /* */ - -FT_END_HEADER - -#endif /* __FTXF86_H__ */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/autohint.h b/Source/ThirdParty/FreeType/include/freetype/internal/autohint.h index 7ef82b8f3c..bae83e7384 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/autohint.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/autohint.h @@ -4,7 +4,7 @@ /* */ /* High-level `autohint' module-specific interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftcalc.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftcalc.h index 8a884f680a..c9ac9d8246 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftcalc.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftcalc.h @@ -4,7 +4,7 @@ /* */ /* Arithmetic computations (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftdebug.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftdebug.h index d110457157..5dcd2b1740 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftdebug.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftdebug.h @@ -4,7 +4,7 @@ /* */ /* Debugging and logging component (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftdriver.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftdriver.h index 902f02fd9d..e82fa8d41f 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftdriver.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftdriver.h @@ -4,7 +4,7 @@ /* */ /* FreeType font driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftgloadr.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftgloadr.h index bebf5dbba2..f41c3df554 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftgloadr.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftgloadr.h @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftmemory.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftmemory.h index fc33b2f50d..59e5b58a57 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftmemory.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftmemory.h @@ -4,7 +4,7 @@ /* */ /* The FreeType memory management macros (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftobjs.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftobjs.h index 25b18a53eb..558409166d 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftobjs.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftobjs.h @@ -4,7 +4,7 @@ /* */ /* The FreeType private base classes (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -342,6 +342,20 @@ FT_BEGIN_HEADER /* this data when first opened. This field exists only if */ /* @FT_CONFIG_OPTION_INCREMENTAL is defined. */ /* */ + /* no_stem_darkening :: */ + /* Overrides the module-level default, see @stem-darkening[cff], */ + /* for example. FALSE and TRUE toggle stem darkening on and off, */ + /* respectively, value~-1 means to use the module/driver default. */ + /* */ + /* random_seed :: */ + /* If positive, override the seed value for the CFF `random' */ + /* operator. Value~0 means to use the font's value. Value~-1 */ + /* means to use the CFF driver's default. */ + /* */ + /* lcd_weights :: */ + /* Overrides the library default with custom weights for the 5-tap */ + /* FIR filter. `{0, 0, 0, 0, 0}' means to use the library default. */ + /* */ /* refcount :: */ /* A counter initialized to~1 at the time an @FT_Face structure is */ /* created. @FT_Reference_Face increments this counter, and */ @@ -350,9 +364,9 @@ FT_BEGIN_HEADER /* */ typedef struct FT_Face_InternalRec_ { - FT_Matrix transform_matrix; - FT_Vector transform_delta; - FT_Int transform_flags; + FT_Matrix transform_matrix; + FT_Vector transform_delta; + FT_Int transform_flags; FT_ServiceCacheRec services; @@ -360,7 +374,13 @@ FT_BEGIN_HEADER FT_Incremental_InterfaceRec* incremental_interface; #endif - FT_Int refcount; + FT_Char no_stem_darkening; + FT_Int32 random_seed; +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + FT_LcdFiveTapFilter lcd_weights; /* preset or custom filter weights */ +#endif + + FT_Int refcount; } FT_Face_InternalRec; @@ -413,8 +433,6 @@ FT_BEGIN_HEADER } FT_GlyphSlot_InternalRec; -#if 0 - /*************************************************************************/ /* */ /* <Struct> */ @@ -422,17 +440,25 @@ FT_BEGIN_HEADER /* */ /* <Description> */ /* This structure contains the internal fields of each FT_Size */ - /* object. Currently, it's empty. */ + /* object. */ + /* */ + /* <Fields> */ + /* module_data :: Data specific to a driver module. */ + /* */ + /* autohint_mode :: The used auto-hinting mode. */ + /* */ + /* autohint_metrics :: Metrics used by the auto-hinter. */ /* */ /*************************************************************************/ typedef struct FT_Size_InternalRec_ { - /* empty */ + void* module_data; - } FT_Size_InternalRec; + FT_Render_Mode autohint_mode; + FT_Size_Metrics autohint_metrics; -#endif + } FT_Size_InternalRec; /*************************************************************************/ @@ -775,12 +801,19 @@ FT_BEGIN_HEADER /* This hook is used by the TrueType debugger. It must be set to an */ /* alternate truetype bytecode interpreter function. */ -#define FT_DEBUG_HOOK_TRUETYPE 0 +#define FT_DEBUG_HOOK_TRUETYPE 0 typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap, FT_Render_Mode render_mode, - FT_Library library ); + FT_Byte* weights ); + + + /* This is the default LCD filter, an in-place, 5-tap FIR filter. */ + FT_BASE( void ) + ft_lcd_filter_fir( FT_Bitmap* bitmap, + FT_Render_Mode mode, + FT_LcdFiveTapFilter weights ); /*************************************************************************/ @@ -821,14 +854,17 @@ FT_BEGIN_HEADER /* handle to the current renderer for the */ /* FT_GLYPH_FORMAT_OUTLINE format. */ /* */ - /* auto_hinter :: XXX */ + /* auto_hinter :: The auto-hinter module interface. */ /* */ /* raster_pool :: The raster object's render pool. This can */ /* ideally be changed dynamically at run-time. */ /* */ /* raster_pool_size :: The size of the render pool in bytes. */ /* */ - /* debug_hooks :: XXX */ + /* debug_hooks :: An array of four function pointers that allow */ + /* debuggers to hook into a font format's */ + /* interpreter. Currently, only the TrueType */ + /* bytecode debugger uses this. */ /* */ /* lcd_filter :: If subpixel rendering is activated, the */ /* selected LCD filter mode. */ @@ -876,7 +912,7 @@ FT_BEGIN_HEADER #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING FT_LcdFilter lcd_filter; FT_Int lcd_extra; /* number of extra pixels */ - FT_Byte lcd_weights[5]; /* filter weights, if any */ + FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */ FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ #endif diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftpic.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftpic.h index 6d800a08a1..0d43ed20f7 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftpic.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services (declaration). */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftrfork.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftrfork.h index 718fa6268b..25a44a4487 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftrfork.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftrfork.h @@ -4,7 +4,7 @@ /* */ /* Embedded resource forks accessor (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Masatake YAMATO and Redhat K.K. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftserv.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftserv.h index 663722f84c..71ef9cac3a 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftserv.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftserv.h @@ -4,7 +4,7 @@ /* */ /* The FreeType services (specification only). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -306,6 +306,30 @@ FT_BEGIN_HEADER { NULL, NULL } \ }; +#define FT_DEFINE_SERVICEDESCREC9( class_, \ + serv_id_1, serv_data_1, \ + serv_id_2, serv_data_2, \ + serv_id_3, serv_data_3, \ + serv_id_4, serv_data_4, \ + serv_id_5, serv_data_5, \ + serv_id_6, serv_data_6, \ + serv_id_7, serv_data_7, \ + serv_id_8, serv_data_8, \ + serv_id_9, serv_data_9 ) \ + static const FT_ServiceDescRec class_[] = \ + { \ + { serv_id_1, serv_data_1 }, \ + { serv_id_2, serv_data_2 }, \ + { serv_id_3, serv_data_3 }, \ + { serv_id_4, serv_data_4 }, \ + { serv_id_5, serv_data_5 }, \ + { serv_id_6, serv_data_6 }, \ + { serv_id_7, serv_data_7 }, \ + { serv_id_8, serv_data_8 }, \ + { serv_id_9, serv_data_9 }, \ + { NULL, NULL } \ + }; + #else /* FT_CONFIG_OPTION_PIC */ #define FT_DEFINE_SERVICEDESCREC1( class_, \ @@ -672,6 +696,65 @@ FT_BEGIN_HEADER return FT_Err_Ok; \ } +#define FT_DEFINE_SERVICEDESCREC9( class_, \ + serv_id_1, serv_data_1, \ + serv_id_2, serv_data_2, \ + serv_id_3, serv_data_3, \ + serv_id_4, serv_data_4, \ + serv_id_5, serv_data_5, \ + serv_id_6, serv_data_6, \ + serv_id_7, serv_data_7, \ + serv_id_8, serv_data_8, \ + serv_id_9, serv_data_9 ) \ + void \ + FT_Destroy_Class_ ## class_( FT_Library library, \ + FT_ServiceDescRec* clazz ) \ + { \ + FT_Memory memory = library->memory; \ + \ + \ + if ( clazz ) \ + FT_FREE( clazz ); \ + } \ + \ + FT_Error \ + FT_Create_Class_ ## class_( FT_Library library, \ + FT_ServiceDescRec** output_class) \ + { \ + FT_ServiceDescRec* clazz = NULL; \ + FT_Error error; \ + FT_Memory memory = library->memory; \ + \ + \ + if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) ) \ + return error; \ + \ + clazz[0].serv_id = serv_id_1; \ + clazz[0].serv_data = serv_data_1; \ + clazz[1].serv_id = serv_id_2; \ + clazz[1].serv_data = serv_data_2; \ + clazz[2].serv_id = serv_id_3; \ + clazz[2].serv_data = serv_data_3; \ + clazz[3].serv_id = serv_id_4; \ + clazz[3].serv_data = serv_data_4; \ + clazz[4].serv_id = serv_id_5; \ + clazz[4].serv_data = serv_data_5; \ + clazz[5].serv_id = serv_id_6; \ + clazz[5].serv_data = serv_data_6; \ + clazz[6].serv_id = serv_id_7; \ + clazz[6].serv_data = serv_data_7; \ + clazz[7].serv_id = serv_id_8; \ + clazz[7].serv_data = serv_data_8; \ + clazz[8].serv_id = serv_id_9; \ + clazz[8].serv_data = serv_data_9; \ + clazz[9].serv_id = NULL; \ + clazz[9].serv_data = NULL; \ + \ + *output_class = clazz; \ + \ + return FT_Err_Ok; \ + } + #endif /* FT_CONFIG_OPTION_PIC */ @@ -714,6 +797,7 @@ FT_BEGIN_HEADER { FT_Pointer service_POSTSCRIPT_FONT_NAME; FT_Pointer service_MULTI_MASTERS; + FT_Pointer service_METRICS_VARIATIONS; FT_Pointer service_GLYPH_DICT; FT_Pointer service_PFR_METRICS; FT_Pointer service_WINFNT; @@ -734,7 +818,7 @@ FT_BEGIN_HEADER * FT_FACE_LOOKUP_SERVICE * * @description: - * This macro is used to lookup a service from a face's driver module + * This macro is used to look up a service from a face's driver module * using its cache. * * @input: diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftstream.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftstream.h index 6d04875657..3e2c07b269 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftstream.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftstream.h @@ -4,7 +4,7 @@ /* */ /* Stream handling (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -502,7 +502,7 @@ FT_BEGIN_HEADER #define FT_STREAM_READ_AT( position, buffer, count ) \ FT_SET_ERROR( FT_Stream_ReadAt( stream, \ (FT_ULong)(position), \ - (FT_Byte*)buffer, \ + (FT_Byte*)(buffer), \ (FT_ULong)(count) ) ) #define FT_STREAM_READ_FIELDS( fields, object ) \ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/fttrace.h b/Source/ThirdParty/FreeType/include/freetype/internal/fttrace.h index efb3355954..caf5fc9460 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/fttrace.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/fttrace.h @@ -4,7 +4,7 @@ /* */ /* Tracing handling (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/ftvalid.h b/Source/ThirdParty/FreeType/include/freetype/internal/ftvalid.h index aac92c9af8..df6f7c5778 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/ftvalid.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/ftvalid.h @@ -4,7 +4,7 @@ /* */ /* FreeType validation support (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/internal.h b/Source/ThirdParty/FreeType/include/freetype/internal/internal.h index 8c3c14c12a..02046813a3 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/internal.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/internal.h @@ -4,7 +4,7 @@ /* */ /* Internal header files (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/psaux.h b/Source/ThirdParty/FreeType/include/freetype/internal/psaux.h index 15dedfd28e..935eb1a9c7 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/psaux.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/psaux.h @@ -5,7 +5,7 @@ /* Auxiliary functions and data structures related to PostScript fonts */ /* (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -817,7 +817,7 @@ FT_BEGIN_HEADER } PSAux_ServiceRec, *PSAux_Service; - /* backwards-compatible type definition */ + /* backward compatible type definition */ typedef PSAux_ServiceRec PSAux_Interface; diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/pshints.h b/Source/ThirdParty/FreeType/include/freetype/internal/pshints.h index e60dc9cd55..49116eb443 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/pshints.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/pshints.h @@ -6,7 +6,7 @@ /* recorders (specification only). These are used to support native */ /* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svbdf.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svbdf.h index c24475fc20..eeebf67da1 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svbdf.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svbdf.h @@ -4,7 +4,7 @@ /* */ /* The FreeType BDF services (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svcid.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svcid.h index dbbe6044a4..cce94d8df6 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svcid.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svcid.h @@ -4,7 +4,7 @@ /* */ /* The FreeType CID font services (specification). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* Derek Clegg and Michael Toftdal. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svfntfmt.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svfntfmt.h index bd295c9c6b..376d9255bb 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svfntfmt.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svfntfmt.h @@ -4,7 +4,7 @@ /* */ /* The FreeType font format service (specification only). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svgldict.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svgldict.h index fff29bc40c..0cd13618d8 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svgldict.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svgldict.h @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph dictionary services (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svgxval.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svgxval.h index fb8ffba83c..71bfa97af8 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svgxval.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svgxval.h @@ -4,7 +4,7 @@ /* */ /* FreeType API for validating TrueTypeGX/AAT tables (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svkern.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svkern.h index a636f1af1c..b8344e96e9 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svkern.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svkern.h @@ -4,7 +4,7 @@ /* */ /* The FreeType Kerning service (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svmetric.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svmetric.h index 7a4fed4233..1f7d5ddd0c 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svmetric.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svmetric.h @@ -4,7 +4,7 @@ /* */ /* The FreeType services for metrics variations (specification). */ /* */ -/* Copyright 2016 by */ +/* Copyright 2016-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -74,10 +74,8 @@ FT_BEGIN_HEADER /* MVAR */ - typedef FT_Error - (*FT_Metrics_Adjust_Func)( FT_Face face, - FT_ULong tag, - FT_Int *avalue ); + typedef void + (*FT_Metrics_Adjust_Func)( FT_Face face ); FT_DEFINE_SERVICE( MetricsVariations ) @@ -140,7 +138,7 @@ FT_BEGIN_HEADER clazz->bsb_adjust = bsb_adjust_; \ clazz->vorg_adjust = vorg_adjust_; \ clazz->metrics_adjust = metrics_adjust_; \ - }; + } #endif /* FT_CONFIG_OPTION_PIC */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svmm.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svmm.h index e54845a54b..1d51cd9090 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svmm.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svmm.h @@ -4,7 +4,7 @@ /* */ /* The FreeType Multiple Masters and GX var services (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -72,6 +72,7 @@ FT_BEGIN_HEADER (*FT_Get_Var_Blend_Func)( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); typedef void diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svotval.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svotval.h index bc929d4bd9..ac84abee46 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svotval.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svotval.h @@ -4,7 +4,7 @@ /* */ /* The FreeType OpenType validation service (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpfr.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpfr.h index d0f7c4df95..c9a182fe39 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpfr.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpfr.h @@ -4,7 +4,7 @@ /* */ /* Internal PFR service functions (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpostnm.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpostnm.h index f124380050..022cdec195 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpostnm.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpostnm.h @@ -4,7 +4,7 @@ /* */ /* The FreeType PostScript name services (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svprop.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svprop.h index 75e62446b2..eb2d4eed15 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svprop.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svprop.h @@ -4,7 +4,7 @@ /* */ /* The FreeType property service (specification). */ /* */ -/* Copyright 2012-2016 by */ +/* Copyright 2012-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpscmap.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpscmap.h index 9acc21690f..b32122e5d6 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpscmap.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpscmap.h @@ -4,7 +4,7 @@ /* */ /* The FreeType PostScript charmap service (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpsinfo.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpsinfo.h index f2c8060440..0220ce529c 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svpsinfo.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svpsinfo.h @@ -4,7 +4,7 @@ /* */ /* The FreeType PostScript info service (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svsfnt.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svsfnt.h index 0f38cf195f..49d18e43e0 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svsfnt.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svsfnt.h @@ -4,7 +4,7 @@ /* */ /* The FreeType SFNT table loading service (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svttcmap.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svttcmap.h index 772c72189e..30f7feec71 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svttcmap.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svttcmap.h @@ -4,7 +4,7 @@ /* */ /* The FreeType TrueType/sfnt cmap extra information service. */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* Masatake YAMATO, Redhat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svtteng.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svtteng.h index c55061a034..e4b368ad40 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svtteng.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svtteng.h @@ -4,7 +4,7 @@ /* */ /* The FreeType TrueType engine query service (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svttglyf.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svttglyf.h index c33edd46de..b7793059fd 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svttglyf.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svttglyf.h @@ -4,7 +4,7 @@ /* */ /* The FreeType TrueType glyph service. */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svwinfnt.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svwinfnt.h index c2f6d4c6d3..c94b7e1073 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svwinfnt.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/services/svwinfnt.h @@ -4,7 +4,7 @@ /* */ /* The FreeType Windows FNT/FONT service (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/services/svxf86nm.h b/Source/ThirdParty/FreeType/include/freetype/internal/services/svxf86nm.h deleted file mode 100644 index ca5d884a83..0000000000 --- a/Source/ThirdParty/FreeType/include/freetype/internal/services/svxf86nm.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************/ -/* */ -/* svxf86nm.h */ -/* */ -/* The FreeType XFree86 services (specification only). */ -/* */ -/* Copyright 2003 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVXF86NM_H__ -#define __SVXF86NM_H__ - -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - - /* - * A trivial service used to return the name of a face's font driver, - * according to the XFree86 nomenclature. Note that the service data - * is a simple constant string pointer. - */ - -#define FT_SERVICE_ID_XF86_NAME "xf86-driver-name" - -#define FT_XF86_FORMAT_TRUETYPE "TrueType" -#define FT_XF86_FORMAT_TYPE_1 "Type 1" -#define FT_XF86_FORMAT_BDF "BDF" -#define FT_XF86_FORMAT_PCF "PCF" -#define FT_XF86_FORMAT_TYPE_42 "Type 42" -#define FT_XF86_FORMAT_CID "CID Type 1" -#define FT_XF86_FORMAT_CFF "CFF" -#define FT_XF86_FORMAT_PFR "PFR" -#define FT_XF86_FORMAT_WINFNT "Windows FNT" - - /* */ - - -FT_END_HEADER - - -#endif /* __SVXF86NM_H__ */ - - -/* END */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/sfnt.h b/Source/ThirdParty/FreeType/include/freetype/internal/sfnt.h index e139315a1f..b8667a003a 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/sfnt.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/sfnt.h @@ -4,7 +4,7 @@ /* */ /* High-level `sfnt' driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -455,6 +455,37 @@ FT_BEGIN_HEADER FT_String** name ); + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Get_Name_ID_Func */ + /* */ + /* <Description> */ + /* Search whether an ENGLISH version for a given name ID is in the */ + /* `name' table. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* nameid :: The name id of the name record to return. */ + /* */ + /* <Out> */ + /* win :: If non-negative, an index into the `name' table with */ + /* the corresponding (3,1) or (3,0) Windows entry. */ + /* */ + /* apple :: If non-negative, an index into the `name' table with */ + /* the corresponding (1,0) Apple entry. */ + /* */ + /* <Return> */ + /* 1 if there is either a win or apple entry (or both), 0 otheriwse. */ + /* */ + typedef FT_Bool + (*TT_Get_Name_ID_Func)( TT_Face face, + FT_UShort nameid, + FT_Int *win, + FT_Int *apple ); + + /*************************************************************************/ /* */ /* <FuncType> */ @@ -588,6 +619,7 @@ FT_BEGIN_HEADER TT_Get_Metrics_Func get_metrics; TT_Get_Name_Func get_name; + TT_Get_Name_ID_Func get_name_id; } SFNT_Interface; @@ -628,7 +660,8 @@ FT_BEGIN_HEADER set_sbit_strike_, \ load_strike_metrics_, \ get_metrics_, \ - get_name_ ) \ + get_name_, \ + get_name_id_ ) \ static const SFNT_Interface class_ = \ { \ goto_table_, \ @@ -661,6 +694,7 @@ FT_BEGIN_HEADER load_strike_metrics_, \ get_metrics_, \ get_name_, \ + get_name_id_ \ }; #else /* FT_CONFIG_OPTION_PIC */ @@ -699,7 +733,8 @@ FT_BEGIN_HEADER set_sbit_strike_, \ load_strike_metrics_, \ get_metrics_, \ - get_name_ ) \ + get_name_, \ + get_name_id_ ) \ void \ FT_Init_Class_ ## class_( FT_Library library, \ SFNT_Interface* clazz ) \ @@ -736,6 +771,7 @@ FT_BEGIN_HEADER clazz->load_strike_metrics = load_strike_metrics_; \ clazz->get_metrics = get_metrics_; \ clazz->get_name = get_name_; \ + clazz->get_name_id = get_name_id_; \ } #endif /* FT_CONFIG_OPTION_PIC */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/t1types.h b/Source/ThirdParty/FreeType/include/freetype/internal/t1types.h index 494c011fc7..b2e35d42d1 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/t1types.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/t1types.h @@ -5,7 +5,7 @@ /* Basic Type1/Type2 type definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/internal/tttypes.h b/Source/ThirdParty/FreeType/include/freetype/internal/tttypes.h index eef3b108c2..c0758e25fc 100644 --- a/Source/ThirdParty/FreeType/include/freetype/internal/tttypes.h +++ b/Source/ThirdParty/FreeType/include/freetype/internal/tttypes.h @@ -5,7 +5,7 @@ /* Basic SFNT/TrueType type definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -243,7 +243,7 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Struct> */ - /* TT_NameEntryRec */ + /* TT_NameRec */ /* */ /* <Description> */ /* A structure modeling TrueType name records. Name records are used */ @@ -267,7 +267,7 @@ FT_BEGIN_HEADER /* string :: A pointer to the string's bytes. Note that these */ /* are usually UTF-16 encoded characters. */ /* */ - typedef struct TT_NameEntryRec_ + typedef struct TT_NameRec_ { FT_UShort platformID; FT_UShort encodingID; @@ -279,9 +279,39 @@ FT_BEGIN_HEADER /* this last field is not defined in the spec */ /* but used by the FreeType engine */ - FT_Byte* string; + FT_Byte* string; - } TT_NameEntryRec, *TT_NameEntry; + } TT_NameRec, *TT_Name; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_LangTagRec */ + /* */ + /* <Description> */ + /* A structure modeling language tag records in SFNT `name' tables, */ + /* introduced in OpenType version 1.6. */ + /* */ + /* <Fields> */ + /* stringLength :: The length of the string in bytes. */ + /* */ + /* stringOffset :: The offset to the string in the `name' table. */ + /* */ + /* string :: A pointer to the string's bytes. Note that these */ + /* are UTF-16BE encoded characters. */ + /* */ + typedef struct TT_LangTagRec_ + { + FT_UShort stringLength; + FT_ULong stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + FT_Byte* string; + + } TT_LangTagRec, *TT_LangTag; /*************************************************************************/ @@ -293,24 +323,30 @@ FT_BEGIN_HEADER /* A structure modeling the TrueType name table. */ /* */ /* <Fields> */ - /* format :: The format of the name table. */ + /* format :: The format of the name table. */ + /* */ + /* numNameRecords :: The number of names in table. */ /* */ - /* numNameRecords :: The number of names in table. */ + /* storageOffset :: The offset of the name table in the `name' */ + /* TrueType table. */ /* */ - /* storageOffset :: The offset of the name table in the `name' */ - /* TrueType table. */ + /* names :: An array of name records. */ /* */ - /* names :: An array of name records. */ + /* numLangTagRecords :: The number of language tags in table. */ /* */ - /* stream :: the file's input stream. */ + /* langTags :: An array of language tag records. */ + /* */ + /* stream :: The file's input stream. */ /* */ typedef struct TT_NameTableRec_ { - FT_UShort format; - FT_UInt numNameRecords; - FT_UInt storageOffset; - TT_NameEntryRec* names; - FT_Stream stream; + FT_UShort format; + FT_UInt numNameRecords; + FT_UInt storageOffset; + TT_NameRec* names; + FT_UInt numLangTagRecords; + TT_LangTagRec* langTags; + FT_Stream stream; } TT_NameTableRec, *TT_NameTable; @@ -1084,49 +1120,8 @@ FT_BEGIN_HEADER #define TT_FACE_FLAG_VAR_BSB ( 1 << 6 ) #define TT_FACE_FLAG_VAR_VORG ( 1 << 7 ) - /* MVAR gasp data */ -#define TT_FACE_FLAG_VAR_GASP_0 ( 1 << 20 ) -#define TT_FACE_FLAG_VAR_GASP_1 ( 1 << 21 ) -#define TT_FACE_FLAG_VAR_GASP_2 ( 1 << 22 ) -#define TT_FACE_FLAG_VAR_GASP_3 ( 1 << 23 ) -#define TT_FACE_FLAG_VAR_GASP_4 ( 1 << 24 ) -#define TT_FACE_FLAG_VAR_GASP_5 ( 1 << 25 ) -#define TT_FACE_FLAG_VAR_GASP_6 ( 1 << 26 ) -#define TT_FACE_FLAG_VAR_GASP_7 ( 1 << 27 ) -#define TT_FACE_FLAG_VAR_GASP_8 ( 1 << 28 ) -#define TT_FACE_FLAG_VAR_GASP_9 ( 1 << 29 ) - - /* The following flag macros are for the field `mvar_support'. */ - - /* remaining MVAR data */ -#define TT_FACE_FLAG_VAR_CPHT ( 1 << 0 ) -#define TT_FACE_FLAG_VAR_HASC ( 1 << 1 ) -#define TT_FACE_FLAG_VAR_HCLA ( 1 << 2 ) -#define TT_FACE_FLAG_VAR_HCLD ( 1 << 3 ) -#define TT_FACE_FLAG_VAR_HCOF ( 1 << 4 ) -#define TT_FACE_FLAG_VAR_HCRN ( 1 << 5 ) -#define TT_FACE_FLAG_VAR_HCRS ( 1 << 6 ) -#define TT_FACE_FLAG_VAR_HDSC ( 1 << 7 ) -#define TT_FACE_FLAG_VAR_HLGP ( 1 << 8 ) -#define TT_FACE_FLAG_VAR_SBXO ( 1 << 9 ) -#define TT_FACE_FLAG_VAR_SBXS ( 1 << 10 ) -#define TT_FACE_FLAG_VAR_SBYO ( 1 << 11 ) -#define TT_FACE_FLAG_VAR_SBYS ( 1 << 12 ) -#define TT_FACE_FLAG_VAR_SPXO ( 1 << 13 ) -#define TT_FACE_FLAG_VAR_SPXS ( 1 << 14 ) -#define TT_FACE_FLAG_VAR_SPYO ( 1 << 15 ) -#define TT_FACE_FLAG_VAR_SPYS ( 1 << 16 ) -#define TT_FACE_FLAG_VAR_STRO ( 1 << 17 ) -#define TT_FACE_FLAG_VAR_STRS ( 1 << 18 ) -#define TT_FACE_FLAG_VAR_UNDO ( 1 << 19 ) -#define TT_FACE_FLAG_VAR_UNDS ( 1 << 20 ) -#define TT_FACE_FLAG_VAR_VASC ( 1 << 21 ) -#define TT_FACE_FLAG_VAR_VCOF ( 1 << 22 ) -#define TT_FACE_FLAG_VAR_VCRN ( 1 << 23 ) -#define TT_FACE_FLAG_VAR_VCRS ( 1 << 24 ) -#define TT_FACE_FLAG_VAR_VDSC ( 1 << 25 ) -#define TT_FACE_FLAG_VAR_VLGP ( 1 << 26 ) -#define TT_FACE_FLAG_VAR_XHGT ( 1 << 27 ) + /* MVAR */ +#define TT_FACE_FLAG_VAR_MVAR ( 1 << 8 ) /*************************************************************************/ @@ -1295,6 +1290,8 @@ FT_BEGIN_HEADER /* */ /* glyf_offset :: The file offset of the `glyf' table. */ /* */ + /* is_cff2 :: Set if the font format is CFF2. */ + /* */ /* doblend :: A boolean which is set if the font should */ /* be blended (this is for GX var). */ /* */ @@ -1312,8 +1309,14 @@ FT_BEGIN_HEADER /* For example, TT_FACE_FLAG_VAR_FVAR is only */ /* set if we have at least one design axis. */ /* */ - /* mvar_support :: Flags that indicate which metrics */ - /* variations are supported. */ + /* var_postscript_prefix :: */ + /* The PostScript name prefix needed for */ + /* constructing a variation font instance's */ + /* PS name . */ + /* */ + /* var_postscript_prefix_len :: */ + /* The length of the `var_postscript_prefix' */ + /* string. */ /* */ /* horz_metrics_size :: The size of the `hmtx' table. */ /* */ @@ -1344,7 +1347,7 @@ FT_BEGIN_HEADER /* */ /* sbit_table_size :: The size of `sbit_table'. */ /* */ - /* sbit_table_type :: The sbit table type (CBLC, SBIX, etc.). */ + /* sbit_table_type :: The sbit table type (CBLC, sbix, etc.). */ /* */ /* sbit_num_strikes :: The number of sbit strikes exposed by */ /* FreeType's API, omitting invalid strikes. */ @@ -1380,7 +1383,7 @@ FT_BEGIN_HEADER /* */ /* sph_compatibility_mode :: */ /* This flag is set if we are in ClearType */ - /* backwards compatibility mode (used by the */ + /* backward compatibility mode (used by the */ /* v38 implementation of the bytecode */ /* interpreter). */ /* */ @@ -1465,7 +1468,7 @@ FT_BEGIN_HEADER /***********************************************************************/ /* */ - /* TrueType-specific fields (ignored by the OTF-Type2 driver) */ + /* TrueType-specific fields (ignored by the CFF driver) */ /* */ /***********************************************************************/ @@ -1500,7 +1503,7 @@ FT_BEGIN_HEADER FT_ULong glyf_len; FT_ULong glyf_offset; /* since 2.7.1 */ - FT_Bool isCFF2; /* since 2.7.1 */ + FT_Bool is_cff2; /* since 2.7.1 */ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Bool doblend; @@ -1508,7 +1511,10 @@ FT_BEGIN_HEADER FT_Bool is_default_instance; /* since 2.7.1 */ FT_UInt32 variation_support; /* since 2.7.1 */ - FT_UInt32 mvar_support; /* since 2.7.1 */ + + const char* var_postscript_prefix; /* since 2.7.2 */ + FT_UInt var_postscript_prefix_len; /* since 2.7.2 */ + #endif /* since version 2.2 */ diff --git a/Source/ThirdParty/FreeType/include/freetype/t1tables.h b/Source/ThirdParty/FreeType/include/freetype/t1tables.h index e272324ba2..3f6b36e108 100644 --- a/Source/ThirdParty/FreeType/include/freetype/t1tables.h +++ b/Source/ThirdParty/FreeType/include/freetype/t1tables.h @@ -5,7 +5,7 @@ /* Basic Type 1/Type 2 tables definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -291,7 +291,7 @@ FT_BEGIN_HEADER } PS_DesignMapRec, *PS_DesignMap; - /* backwards-compatible definition */ + /* backward compatible definition */ typedef PS_DesignMapRec T1_DesignMap; @@ -326,7 +326,7 @@ FT_BEGIN_HEADER } PS_BlendRec, *PS_Blend; - /* backwards-compatible definition */ + /* backward compatible definition */ typedef PS_BlendRec T1_Blend; diff --git a/Source/ThirdParty/FreeType/include/freetype/ttnameid.h b/Source/ThirdParty/FreeType/include/freetype/ttnameid.h index ce707f1645..494d677186 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ttnameid.h +++ b/Source/ThirdParty/FreeType/include/freetype/ttnameid.h @@ -4,7 +4,7 @@ /* */ /* TrueType name ID definitions (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -36,7 +36,7 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ /* Possible values for the `platform' identifier code in the name */ - /* records of the TTF `name' table. */ + /* records of an SFNT `name' table. */ /* */ /*************************************************************************/ @@ -119,14 +119,19 @@ FT_BEGIN_HEADER * TT_APPLE_ID_VARIANT_SELECTOR :: * From Adobe, not Apple. Not a normal cmap. Specifies variations * on a real cmap. + * + * TT_APPLE_ID_FULL_UNICODE :: + * Used for fallback fonts that provide complete Unicode coverage with + * a type~13 cmap. */ -#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ -#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ -#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ -#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ +#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ +#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ +#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ +#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ #define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ -#define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ +#define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ +#define TT_APPLE_ID_FULL_UNICODE 6 /* used with type 13 cmaps */ /*********************************************************************** @@ -137,42 +142,6 @@ FT_BEGIN_HEADER * @description: * A list of valid values for the `encoding_id' for * @TT_PLATFORM_MACINTOSH charmaps and name entries. - * - * @values: - * TT_MAC_ID_ROMAN :: - * TT_MAC_ID_JAPANESE :: - * TT_MAC_ID_TRADITIONAL_CHINESE :: - * TT_MAC_ID_KOREAN :: - * TT_MAC_ID_ARABIC :: - * TT_MAC_ID_HEBREW :: - * TT_MAC_ID_GREEK :: - * TT_MAC_ID_RUSSIAN :: - * TT_MAC_ID_RSYMBOL :: - * TT_MAC_ID_DEVANAGARI :: - * TT_MAC_ID_GURMUKHI :: - * TT_MAC_ID_GUJARATI :: - * TT_MAC_ID_ORIYA :: - * TT_MAC_ID_BENGALI :: - * TT_MAC_ID_TAMIL :: - * TT_MAC_ID_TELUGU :: - * TT_MAC_ID_KANNADA :: - * TT_MAC_ID_MALAYALAM :: - * TT_MAC_ID_SINHALESE :: - * TT_MAC_ID_BURMESE :: - * TT_MAC_ID_KHMER :: - * TT_MAC_ID_THAI :: - * TT_MAC_ID_LAOTIAN :: - * TT_MAC_ID_GEORGIAN :: - * TT_MAC_ID_ARMENIAN :: - * TT_MAC_ID_MALDIVIAN :: - * TT_MAC_ID_SIMPLIFIED_CHINESE :: - * TT_MAC_ID_TIBETAN :: - * TT_MAC_ID_MONGOLIAN :: - * TT_MAC_ID_GEEZ :: - * TT_MAC_ID_SLAVIC :: - * TT_MAC_ID_VIETNAMESE :: - * TT_MAC_ID_SINDHI :: - * TT_MAC_ID_UNINTERP :: */ #define TT_MAC_ID_ROMAN 0 @@ -247,44 +216,47 @@ FT_BEGIN_HEADER * * @values: * TT_MS_ID_SYMBOL_CS :: - * Corresponds to Microsoft symbol encoding. See - * @FT_ENCODING_MS_SYMBOL. + * Microsoft symbol encoding. See @FT_ENCODING_MS_SYMBOL. * * TT_MS_ID_UNICODE_CS :: - * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See + * Microsoft WGL4 charmap, matching Unicode. See * @FT_ENCODING_UNICODE. * * TT_MS_ID_SJIS :: - * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS. + * Shift JIS Japanese encoding. See @FT_ENCODING_SJIS. * - * TT_MS_ID_GB2312 :: - * Corresponds to Simplified Chinese as used in Mainland China. See - * @FT_ENCODING_GB2312. + * TT_MS_ID_PRC :: + * Chinese encodings as used in the People's Republic of China (PRC). + * This means the encodings GB~2312 and its supersets GBK and + * GB~18030. See @FT_ENCODING_PRC. * * TT_MS_ID_BIG_5 :: - * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. - * See @FT_ENCODING_BIG5. + * Traditional Chinese as used in Taiwan and Hong Kong. See + * @FT_ENCODING_BIG5. * * TT_MS_ID_WANSUNG :: - * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG. + * Korean Extended Wansung encoding. See @FT_ENCODING_WANSUNG. * * TT_MS_ID_JOHAB :: - * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB. + * Korean Johab encoding. See @FT_ENCODING_JOHAB. * * TT_MS_ID_UCS_4 :: - * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to - * the OpenType specification version 1.4 (mid-2001.) + * UCS-4 or UTF-32 charmaps. This has been added to the OpenType + * specification version 1.4 (mid-2001). */ #define TT_MS_ID_SYMBOL_CS 0 #define TT_MS_ID_UNICODE_CS 1 #define TT_MS_ID_SJIS 2 -#define TT_MS_ID_GB2312 3 +#define TT_MS_ID_PRC 3 #define TT_MS_ID_BIG_5 4 #define TT_MS_ID_WANSUNG 5 #define TT_MS_ID_JOHAB 6 #define TT_MS_ID_UCS_4 10 + /* this value is deprecated */ +#define TT_MS_ID_GB2312 TT_MS_ID_PRC + /*********************************************************************** * @@ -312,17 +284,22 @@ FT_BEGIN_HEADER #define TT_ADOBE_ID_LATIN_1 3 - /*************************************************************************/ - /* */ - /* Possible values of the language identifier field in the name records */ - /* of the TTF `name' table if the `platform' identifier code is */ - /* TT_PLATFORM_MACINTOSH. These values are also used as return values */ - /* for function @FT_Get_CMap_Language_ID. */ - /* */ - /* The canonical source for the Apple assigned Language ID's is at */ - /* */ - /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html */ - /* */ + /*********************************************************************** + * + * @enum: + * TT_MAC_LANGID_XXX + * + * @description: + * Possible values of the language identifier field in the name records + * of the SFNT `name' table if the `platform' identifier code is + * @TT_PLATFORM_MACINTOSH. These values are also used as return values + * for function @FT_Get_CMap_Language_ID. + * + * The canonical source for Apple's IDs is + * + * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html + */ + #define TT_MAC_LANGID_ENGLISH 0 #define TT_MAC_LANGID_FRENCH 1 #define TT_MAC_LANGID_GERMAN 2 @@ -433,15 +410,6 @@ FT_BEGIN_HEADER #define TT_MAC_LANGID_JAVANESE 138 #define TT_MAC_LANGID_SUNDANESE 139 - -#if 0 /* these seem to be errors that have been dropped */ - -#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 -#define TT_MAC_LANGID_IRISH_GAELIC 141 - -#endif - - /* The following codes are new as of 2000-03-10 */ #define TT_MAC_LANGID_GALICIAN 140 #define TT_MAC_LANGID_AFRIKAANS 141 @@ -456,18 +424,30 @@ FT_BEGIN_HEADER #define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 - /*************************************************************************/ - /* */ - /* Possible values of the language identifier field in the name records */ - /* of the TTF `name' table if the `platform' identifier code is */ - /* TT_PLATFORM_MICROSOFT. */ - /* */ - /* The canonical source for the MS assigned LCIDs is */ - /* */ - /* http://www.microsoft.com/globaldev/reference/lcid-all.mspx */ - /* */ + /*********************************************************************** + * + * @enum: + * TT_MS_LANGID_XXX + * + * @description: + * Possible values of the language identifier field in the name records + * of the SFNT `name' table if the `platform' identifier code is + * @TT_PLATFORM_MICROSOFT. These values are also used as return values + * for function @FT_Get_CMap_Language_ID. + * + * The canonical source for Microsoft's IDs is + * + * http://www.microsoft.com/globaldev/reference/lcid-all.mspx , + * + * however, we only provide macros for language identifiers present in + * the OpenType specification: Microsoft has abandoned the concept of + * LCIDs (language code identifiers), and format~1 of the `name' table + * provides a better mechanism for languages not covered here. + * + * More legacy values not listed in the reference can be found in the + * @FT_TRUETYPE_IDS_H header file. + */ -#define TT_MS_LANGID_ARABIC_GENERAL 0x0001 #define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 #define TT_MS_LANGID_ARABIC_IRAQ 0x0801 #define TT_MS_LANGID_ARABIC_EGYPT 0x0C01 @@ -485,39 +465,20 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_ARABIC_BAHRAIN 0x3C01 #define TT_MS_LANGID_ARABIC_QATAR 0x4001 #define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 -#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 -#define TT_MS_LANGID_CHINESE_GENERAL 0x0004 +#define TT_MS_LANGID_CATALAN_CATALAN 0x0403 #define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 #define TT_MS_LANGID_CHINESE_PRC 0x0804 #define TT_MS_LANGID_CHINESE_HONG_KONG 0x0C04 #define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 - -#if 1 /* this looks like the correct value */ -#define TT_MS_LANGID_CHINESE_MACAU 0x1404 -#else /* but beware, Microsoft may change its mind... - the most recent Word reference has the following: */ -#define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG -#endif - -#if 0 /* used only with .NET `cultures'; commented out */ -#define TT_MS_LANGID_CHINESE_TRADITIONAL 0x7C04 -#endif - +#define TT_MS_LANGID_CHINESE_MACAO 0x1404 #define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 #define TT_MS_LANGID_DANISH_DENMARK 0x0406 #define TT_MS_LANGID_GERMAN_GERMANY 0x0407 #define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 #define TT_MS_LANGID_GERMAN_AUSTRIA 0x0C07 #define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 -#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 +#define TT_MS_LANGID_GERMAN_LIECHTENSTEIN 0x1407 #define TT_MS_LANGID_GREEK_GREECE 0x0408 - - /* don't ask what this one means... It is commented out currently. */ -#if 0 -#define TT_MS_LANGID_GREEK_GREECE2 0x2008 -#endif - -#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 #define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 #define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0C09 @@ -531,14 +492,12 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2C09 #define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 #define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 -#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809 -#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3C09 #define TT_MS_LANGID_ENGLISH_INDIA 0x4009 #define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 #define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 #define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040A #define TT_MS_LANGID_SPANISH_MEXICO 0x080A -#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0C0A +#define TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT 0x0C0A #define TT_MS_LANGID_SPANISH_GUATEMALA 0x100A #define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140A #define TT_MS_LANGID_SPANISH_PANAMA 0x180A @@ -557,9 +516,6 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_SPANISH_NICARAGUA 0x4C0A #define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500A #define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540A - /* The following ID blatantly violate MS specs by using a */ - /* sublanguage > 0x1F. */ -#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40AU #define TT_MS_LANGID_FINNISH_FINLAND 0x040B #define TT_MS_LANGID_FRENCH_FRANCE 0x040C #define TT_MS_LANGID_FRENCH_BELGIUM 0x080C @@ -567,27 +523,13 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100C #define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140C #define TT_MS_LANGID_FRENCH_MONACO 0x180C -#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1C0C -#define TT_MS_LANGID_FRENCH_REUNION 0x200C -#define TT_MS_LANGID_FRENCH_CONGO 0x240C - /* which was formerly: */ -#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO -#define TT_MS_LANGID_FRENCH_SENEGAL 0x280C -#define TT_MS_LANGID_FRENCH_CAMEROON 0x2C0C -#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300C -#define TT_MS_LANGID_FRENCH_MALI 0x340C -#define TT_MS_LANGID_FRENCH_MOROCCO 0x380C -#define TT_MS_LANGID_FRENCH_HAITI 0x3C0C - /* and another violation of the spec (see 0xE40AU) */ -#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40CU #define TT_MS_LANGID_HEBREW_ISRAEL 0x040D #define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040E #define TT_MS_LANGID_ICELANDIC_ICELAND 0x040F #define TT_MS_LANGID_ITALIAN_ITALY 0x0410 #define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 #define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 -#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 -#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_KOREAN_KOREA 0x0412 #define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 #define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 #define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 @@ -595,26 +537,17 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_POLISH_POLAND 0x0415 #define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 #define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 -#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 +#define TT_MS_LANGID_ROMANSH_SWITZERLAND 0x0417 #define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 -#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 #define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 -#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 #define TT_MS_LANGID_CROATIAN_CROATIA 0x041A #define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081A #define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0C1A - -#if 0 /* this used to be this value, but it looks like we were wrong */ -#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101A -#else /* current sources say */ #define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101A #define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141A - /* and XPsp2 Platform SDK added (2004-07-26) */ - /* Names are shortened to be significant within 40 chars. */ #define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181A -#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181A -#endif - +#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x1C1A +#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZ_CYRILLIC 0x201A #define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041B #define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041C #define TT_MS_LANGID_SWEDISH_SWEDEN 0x041D @@ -622,36 +555,30 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_THAI_THAILAND 0x041E #define TT_MS_LANGID_TURKISH_TURKEY 0x041F #define TT_MS_LANGID_URDU_PAKISTAN 0x0420 -#define TT_MS_LANGID_URDU_INDIA 0x0820 #define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 #define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 #define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 -#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 +#define TT_MS_LANGID_SLOVENIAN_SLOVENIA 0x0424 #define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 #define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 #define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 -#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 #define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 -#define TT_MS_LANGID_FARSI_IRAN 0x0429 #define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042A #define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042B #define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042C #define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082C -#define TT_MS_LANGID_BASQUE_SPAIN 0x042D -#define TT_MS_LANGID_SORBIAN_GERMANY 0x042E +#define TT_MS_LANGID_BASQUE_BASQUE 0x042D +#define TT_MS_LANGID_UPPER_SORBIAN_GERMANY 0x042E +#define TT_MS_LANGID_LOWER_SORBIAN_GERMANY 0x082E #define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042F -#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 -#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 -#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 -#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 -#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 -#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 +#define TT_MS_LANGID_SETSWANA_SOUTH_AFRICA 0x0432 +#define TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA 0x0434 +#define TT_MS_LANGID_ISIZULU_SOUTH_AFRICA 0x0435 #define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 #define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 #define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 #define TT_MS_LANGID_HINDI_INDIA 0x0439 #define TT_MS_LANGID_MALTESE_MALTA 0x043A - /* Added by XPsp2 Platform SDK (2004-07-26) */ #define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043B #define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083B #define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3B @@ -661,37 +588,21 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3B #define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203B #define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243B - /* ... and we also keep our old identifier... */ -#define TT_MS_LANGID_SAAMI_LAPONIA 0x043B - -#if 0 /* this seems to be a previous inversion */ -#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C -#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C -#else -#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C -#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C -#endif - -#define TT_MS_LANGID_YIDDISH_GERMANY 0x043D +#define TT_MS_LANGID_IRISH_IRELAND 0x083C #define TT_MS_LANGID_MALAY_MALAYSIA 0x043E #define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083E -#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043F -#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440 - /* alias declared in Windows 2000 */ -#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \ - TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN - -#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 +#define TT_MS_LANGID_KAZAKH_KAZAKHSTAN 0x043F +#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/ 0x0440 +#define TT_MS_LANGID_KISWAHILI_KENYA 0x0441 #define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 #define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 #define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 -#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 +#define TT_MS_LANGID_TATAR_RUSSIA 0x0444 #define TT_MS_LANGID_BENGALI_INDIA 0x0445 #define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 #define TT_MS_LANGID_PUNJABI_INDIA 0x0446 -#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846 #define TT_MS_LANGID_GUJARATI_INDIA 0x0447 -#define TT_MS_LANGID_ORIYA_INDIA 0x0448 +#define TT_MS_LANGID_ODIA_INDIA 0x0448 #define TT_MS_LANGID_TAMIL_INDIA 0x0449 #define TT_MS_LANGID_TELUGU_INDIA 0x044A #define TT_MS_LANGID_KANNADA_INDIA 0x044B @@ -700,142 +611,241 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_MARATHI_INDIA 0x044E #define TT_MS_LANGID_SANSKRIT_INDIA 0x044F #define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 -#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850 -#define TT_MS_LANGID_TIBETAN_CHINA 0x0451 - /* Don't use the next constant! It has */ - /* (1) the wrong spelling (Dzonghka) */ - /* (2) Microsoft doesn't officially define it -- */ - /* at least it is not in the List of Local */ - /* ID Values. */ - /* (3) Dzongkha is not the same language as */ - /* Tibetan, so merging it is wrong anyway. */ - /* */ - /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW. */ -#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851 - -#if 0 - /* the following used to be defined */ -#define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451 - /* ... but it was changed; */ -#else - /* So we will continue to #define it, but with the correct value */ -#define TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_DZONGHKA_BHUTAN -#endif - -#define TT_MS_LANGID_WELSH_WALES 0x0452 +#define TT_MS_LANGID_MONGOLIAN_PRC 0x0850 +#define TT_MS_LANGID_TIBETAN_PRC 0x0451 +#define TT_MS_LANGID_WELSH_UNITED_KINGDOM 0x0452 #define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 #define TT_MS_LANGID_LAO_LAOS 0x0454 -#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455 -#define TT_MS_LANGID_GALICIAN_SPAIN 0x0456 +#define TT_MS_LANGID_GALICIAN_GALICIAN 0x0456 #define TT_MS_LANGID_KONKANI_INDIA 0x0457 -#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458 -#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459 -#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859 - /* Missing a LCID for Sindhi in Devanagari script */ #define TT_MS_LANGID_SYRIAC_SYRIA 0x045A -#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045B -#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045C +#define TT_MS_LANGID_SINHALA_SRI_LANKA 0x045B #define TT_MS_LANGID_INUKTITUT_CANADA 0x045D +#define TT_MS_LANGID_INUKTITUT_CANADA_LATIN 0x085D #define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045E -#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045F -#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085F - /* Missing a LCID for Tifinagh script */ -#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460 - /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */ - /* script is yet unclear... might be Arabic, Nagari or Sharada */ -#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860 - /* ... and aliased (by MS) for compatibility reasons. */ -#define TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_KASHMIRI_SASIA +#define TT_MS_LANGID_TAMAZIGHT_ALGERIA 0x085F #define TT_MS_LANGID_NEPALI_NEPAL 0x0461 -#define TT_MS_LANGID_NEPALI_INDIA 0x0861 #define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 #define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 #define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 #define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 - /* alias declared in Windows 2000 */ -#define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES -#define TT_MS_LANGID_EDO_NIGERIA 0x0466 -#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467 #define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 -#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469 #define TT_MS_LANGID_YORUBA_NIGERIA 0x046A #define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046B #define TT_MS_LANGID_QUECHUA_ECUADOR 0x086B #define TT_MS_LANGID_QUECHUA_PERU 0x0C6B -#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046C - /* Also spelled by XPsp2 Platform SDK (2004-07-26) */ -#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \ - TT_MS_LANGID_SEPEDI_SOUTH_AFRICA - /* language codes 0x046D, 0x046E and 0x046F are (still) unknown. */ +#define TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA 0x046C +#define TT_MS_LANGID_BASHKIR_RUSSIA 0x046D +#define TT_MS_LANGID_LUXEMBOURGISH_LUXEMBOURG 0x046E +#define TT_MS_LANGID_GREENLANDIC_GREENLAND 0x046F #define TT_MS_LANGID_IGBO_NIGERIA 0x0470 +#define TT_MS_LANGID_YI_PRC 0x0478 +#define TT_MS_LANGID_MAPUDUNGUN_CHILE 0x047A +#define TT_MS_LANGID_MOHAWK_MOHAWK 0x047C +#define TT_MS_LANGID_BRETON_FRANCE 0x047E +#define TT_MS_LANGID_UIGHUR_PRC 0x0480 +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 +#define TT_MS_LANGID_OCCITAN_FRANCE 0x0482 +#define TT_MS_LANGID_CORSICAN_FRANCE 0x0483 +#define TT_MS_LANGID_ALSATIAN_FRANCE 0x0484 +#define TT_MS_LANGID_YAKUT_RUSSIA 0x0485 +#define TT_MS_LANGID_KICHE_GUATEMALA 0x0486 +#define TT_MS_LANGID_KINYARWANDA_RWANDA 0x0487 +#define TT_MS_LANGID_WOLOF_SENEGAL 0x0488 +#define TT_MS_LANGID_DARI_AFGHANISTAN 0x048C + + /* */ + + + /* legacy macro definitions not present in OpenType 1.8.1 */ +#define TT_MS_LANGID_ARABIC_GENERAL 0x0001 +#define TT_MS_LANGID_CATALAN_SPAIN \ + TT_MS_LANGID_CATALAN_CATALAN +#define TT_MS_LANGID_CHINESE_GENERAL 0x0004 +#define TT_MS_LANGID_CHINESE_MACAU \ + TT_MS_LANGID_CHINESE_MACAO +#define TT_MS_LANGID_GERMAN_LIECHTENSTEI \ + TT_MS_LANGID_GERMAN_LIECHTENSTEIN +#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009 +#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809 +#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3C09 +#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT \ + TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT +#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40AU +#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1C0C +#define TT_MS_LANGID_FRENCH_REUNION 0x200C +#define TT_MS_LANGID_FRENCH_CONGO 0x240C + /* which was formerly: */ +#define TT_MS_LANGID_FRENCH_ZAIRE \ + TT_MS_LANGID_FRENCH_CONGO +#define TT_MS_LANGID_FRENCH_SENEGAL 0x280C +#define TT_MS_LANGID_FRENCH_CAMEROON 0x2C0C +#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300C +#define TT_MS_LANGID_FRENCH_MALI 0x340C +#define TT_MS_LANGID_FRENCH_MOROCCO 0x380C +#define TT_MS_LANGID_FRENCH_HAITI 0x3C0C +#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40CU +#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA \ + TT_MS_LANGID_KOREAN_KOREA +#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND \ + TT_MS_LANGID_ROMANSH_SWITZERLAND +#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 +#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 +#define TT_MS_LANGID_URDU_INDIA 0x0820 +#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 +#define TT_MS_LANGID_SLOVENE_SLOVENIA \ + TT_MS_LANGID_SLOVENIAN_SLOVENIA +#define TT_MS_LANGID_FARSI_IRAN 0x0429 +#define TT_MS_LANGID_BASQUE_SPAIN \ + TT_MS_LANGID_BASQUE_BASQUE +#define TT_MS_LANGID_SORBIAN_GERMANY \ + TT_MS_LANGID_UPPER_SORBIAN_GERMANY +#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 +#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 +#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA \ + TT_MS_LANGID_SETSWANA_SOUTH_AFRICA +#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 +#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA \ + TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA +#define TT_MS_LANGID_ZULU_SOUTH_AFRICA \ + TT_MS_LANGID_ISIZULU_SOUTH_AFRICA +#define TT_MS_LANGID_SAAMI_LAPONIA 0x043B + /* the next two values are incorrectly inverted */ +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C +#define TT_MS_LANGID_YIDDISH_GERMANY 0x043D +#define TT_MS_LANGID_KAZAK_KAZAKSTAN \ + TT_MS_LANGID_KAZAKH_KAZAKHSTAN +#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \ + TT_MS_LANGID_KYRGYZ_KYRGYZSTAN +#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN \ + TT_MS_LANGID_KYRGYZ_KYRGYZSTAN +#define TT_MS_LANGID_SWAHILI_KENYA \ + TT_MS_LANGID_KISWAHILI_KENYA +#define TT_MS_LANGID_TATAR_TATARSTAN \ + TT_MS_LANGID_TATAR_RUSSIA +#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846 +#define TT_MS_LANGID_ORIYA_INDIA \ + TT_MS_LANGID_ODIA_INDIA +#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN \ + TT_MS_LANGID_MONGOLIAN_PRC +#define TT_MS_LANGID_TIBETAN_CHINA \ + TT_MS_LANGID_TIBETAN_PRC +#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851 +#define TT_MS_LANGID_TIBETAN_BHUTAN \ + TT_MS_LANGID_DZONGHKA_BHUTAN +#define TT_MS_LANGID_WELSH_WALES \ + TT_MS_LANGID_WELSH_UNITED_KINGDOM +#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455 +#define TT_MS_LANGID_GALICIAN_SPAIN \ + TT_MS_LANGID_GALICIAN_GALICIAN +#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458 +#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459 +#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859 +#define TT_MS_LANGID_SINHALESE_SRI_LANKA \ + TT_MS_LANGID_SINHALA_SRI_LANKA +#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045C +#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045F +#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN \ + TT_MS_LANGID_TAMAZIGHT_ALGERIA +#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460 +#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860 +#define TT_MS_LANGID_KASHMIRI_INDIA \ + TT_MS_LANGID_KASHMIRI_SASIA +#define TT_MS_LANGID_NEPALI_INDIA 0x0861 +#define TT_MS_LANGID_DIVEHI_MALDIVES \ + TT_MS_LANGID_DHIVEHI_MALDIVES +#define TT_MS_LANGID_EDO_NIGERIA 0x0466 +#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467 +#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469 +#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA \ + TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA +#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \ + TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA #define TT_MS_LANGID_KANURI_NIGERIA 0x0471 #define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472 #define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473 #define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873 - /* also spelled in the `Passport SDK' list as: */ -#define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA +#define TT_MS_LANGID_TIGRIGNA_ERYTREA \ + TT_MS_LANGID_TIGRIGNA_ERYTHREA #define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474 #define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475 #define TT_MS_LANGID_LATIN 0x0476 #define TT_MS_LANGID_SOMALI_SOMALIA 0x0477 - /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */ - /* not written (but OTOH the peculiar writing system is worth */ - /* studying). */ -#define TT_MS_LANGID_YI_CHINA 0x0478 +#define TT_MS_LANGID_YI_CHINA \ + TT_MS_LANGID_YI_PRC #define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479 - /* language codes from 0x047A to 0x047F are (still) unknown. */ -#define TT_MS_LANGID_UIGHUR_CHINA 0x0480 -#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 +#define TT_MS_LANGID_UIGHUR_CHINA \ + TT_MS_LANGID_UIGHUR_PRC -#if 0 /* not deemed useful for fonts */ -#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04FF -#endif + /*********************************************************************** + * + * @enum: + * TT_NAME_ID_XXX + * + * @description: + * Possible values of the `name' identifier field in the name records of + * an SFNT `name' table. These values are platform independent. + */ - /*************************************************************************/ - /* */ - /* Possible values of the `name' identifier field in the name records of */ - /* the TTF `name' table. These values are platform independent. */ - /* */ -#define TT_NAME_ID_COPYRIGHT 0 -#define TT_NAME_ID_FONT_FAMILY 1 -#define TT_NAME_ID_FONT_SUBFAMILY 2 -#define TT_NAME_ID_UNIQUE_ID 3 -#define TT_NAME_ID_FULL_NAME 4 -#define TT_NAME_ID_VERSION_STRING 5 -#define TT_NAME_ID_PS_NAME 6 -#define TT_NAME_ID_TRADEMARK 7 +#define TT_NAME_ID_COPYRIGHT 0 +#define TT_NAME_ID_FONT_FAMILY 1 +#define TT_NAME_ID_FONT_SUBFAMILY 2 +#define TT_NAME_ID_UNIQUE_ID 3 +#define TT_NAME_ID_FULL_NAME 4 +#define TT_NAME_ID_VERSION_STRING 5 +#define TT_NAME_ID_PS_NAME 6 +#define TT_NAME_ID_TRADEMARK 7 /* the following values are from the OpenType spec */ -#define TT_NAME_ID_MANUFACTURER 8 -#define TT_NAME_ID_DESIGNER 9 -#define TT_NAME_ID_DESCRIPTION 10 -#define TT_NAME_ID_VENDOR_URL 11 -#define TT_NAME_ID_DESIGNER_URL 12 -#define TT_NAME_ID_LICENSE 13 -#define TT_NAME_ID_LICENSE_URL 14 +#define TT_NAME_ID_MANUFACTURER 8 +#define TT_NAME_ID_DESIGNER 9 +#define TT_NAME_ID_DESCRIPTION 10 +#define TT_NAME_ID_VENDOR_URL 11 +#define TT_NAME_ID_DESIGNER_URL 12 +#define TT_NAME_ID_LICENSE 13 +#define TT_NAME_ID_LICENSE_URL 14 /* number 15 is reserved */ -#define TT_NAME_ID_PREFERRED_FAMILY 16 -#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 -#define TT_NAME_ID_MAC_FULL_NAME 18 +#define TT_NAME_ID_TYPOGRAPHIC_FAMILY 16 +#define TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY 17 +#define TT_NAME_ID_MAC_FULL_NAME 18 /* The following code is new as of 2000-01-21 */ -#define TT_NAME_ID_SAMPLE_TEXT 19 +#define TT_NAME_ID_SAMPLE_TEXT 19 /* This is new in OpenType 1.3 */ -#define TT_NAME_ID_CID_FINDFONT_NAME 20 +#define TT_NAME_ID_CID_FINDFONT_NAME 20 /* This is new in OpenType 1.5 */ -#define TT_NAME_ID_WWS_FAMILY 21 -#define TT_NAME_ID_WWS_SUBFAMILY 22 +#define TT_NAME_ID_WWS_FAMILY 21 +#define TT_NAME_ID_WWS_SUBFAMILY 22 + /* This is new in OpenType 1.7 */ +#define TT_NAME_ID_LIGHT_BACKGROUND 23 +#define TT_NAME_ID_DARK_BACKGROUND 24 - /*************************************************************************/ - /* */ - /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ - /* */ - /* Updated 08-Nov-2008. */ - /* */ + /* This is new in OpenType 1.8 */ +#define TT_NAME_ID_VARIATIONS_PREFIX 25 + + /* these two values are deprecated */ +#define TT_NAME_ID_PREFERRED_FAMILY TT_NAME_ID_TYPOGRAPHIC_FAMILY +#define TT_NAME_ID_PREFERRED_SUBFAMILY TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY + + + /*********************************************************************** + * + * @enum: + * TT_UCR_XXX + * + * @description: + * Possible bit mask values for the `ulUnicodeRangeX' fields in an SFNT + * `OS/2' table. + */ + + /* ulUnicodeRange1 */ + /* --------------- */ /* Bit 0 Basic Latin */ #define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ @@ -857,7 +867,7 @@ FT_BEGIN_HEADER /* U+A700-U+A71F */ /* Bit 6 Combining Diacritical Marks */ /* Combining Diacritical Marks Supplement */ -#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS (1L << 6) /* U+0300-U+036F */ /* U+1DC0-U+1DFF */ /* Bit 7 Greek and Coptic */ #define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ @@ -925,12 +935,17 @@ FT_BEGIN_HEADER /* Supplemental Punctuation */ #define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ /* U+2E00-U+2E7F */ + + /* ulUnicodeRange2 */ + /* --------------- */ + /* Bit 32 Superscripts And Subscripts */ #define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ /* Bit 33 Currency Symbols */ #define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ /* Bit 34 Combining Diacritical Marks For Symbols */ -#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ + (1L << 2) /* U+20D0-U+20FF */ /* Bit 35 Letterlike Symbols */ #define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ /* Bit 36 Number Forms */ @@ -996,13 +1011,13 @@ FT_BEGIN_HEADER /* Bit 57 High Surrogates */ /* High Private Use Surrogates */ /* Low Surrogates */ - /* */ + /* According to OpenType specs v.1.3+, */ /* setting bit 57 implies that there is */ /* at least one codepoint beyond the */ /* Basic Multilingual Plane that is */ /* supported by this font. So it really */ - /* means >= U+10000 */ + /* means >= U+10000. */ #define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ /* U+DB80-U+DBFF */ /* U+DC00-U+DFFF */ @@ -1034,7 +1049,11 @@ FT_BEGIN_HEADER /* Bit 62 Alphabetic Presentation Forms */ #define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ /* Bit 63 Arabic Presentation Forms-A */ -#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1L << 31) /* U+FB50-U+FDFF */ + + /* ulUnicodeRange3 */ + /* --------------- */ + /* Bit 64 Combining Half Marks */ #define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ /* Bit 65 Vertical forms */ @@ -1044,7 +1063,7 @@ FT_BEGIN_HEADER /* Bit 66 Small Form Variants */ #define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ /* Bit 67 Arabic Presentation Forms-B */ -#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1L << 3) /* U+FE70-U+FEFE */ /* Bit 68 Halfwidth and Fullwidth Forms */ #define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ /* Bit 69 Specials */ @@ -1123,6 +1142,10 @@ FT_BEGIN_HEADER #define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ /* Bit 95 New Tai Lue */ #define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ + + /* ulUnicodeRange4 */ + /* --------------- */ + /* Bit 96 Buginese */ #define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ /* Bit 97 Glagolitic */ @@ -1191,42 +1214,18 @@ FT_BEGIN_HEADER /*U+1F000-U+1F02F*/ /* Bit 123-127 Reserved for process-internal usage */ + /* */ - /*************************************************************************/ - /* */ - /* Some compilers have a very limited length of identifiers. */ - /* */ -#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) -#define HAVE_LIMIT_ON_IDENTS -#endif - - -#ifndef HAVE_LIMIT_ON_IDENTS - - - /*************************************************************************/ - /* */ - /* Here some alias #defines in order to be clearer. */ - /* */ - /* These are not always #defined to stay within the 31~character limit, */ - /* which some compilers have. */ - /* */ - /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */ - /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ - /* If you get a warning with such a compiler, use the -i40 switch. */ - /* */ -#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ - TT_UCR_ARABIC_PRESENTATIONS_A -#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ - TT_UCR_ARABIC_PRESENTATIONS_B - -#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ - TT_UCR_COMBINING_DIACRITICS -#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ - TT_UCR_COMBINING_DIACRITICS_SYMB - + /* for backward compatibility with older FreeType versions */ +#define TT_UCR_ARABIC_PRESENTATION_A \ + TT_UCR_ARABIC_PRESENTATION_FORMS_A +#define TT_UCR_ARABIC_PRESENTATION_B \ + TT_UCR_ARABIC_PRESENTATION_FORMS_B -#endif /* !HAVE_LIMIT_ON_IDENTS */ +#define TT_UCR_COMBINING_DIACRITICS \ + TT_UCR_COMBINING_DIACRITICAL_MARKS +#define TT_UCR_COMBINING_DIACRITICS_SYMB \ + TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB FT_END_HEADER diff --git a/Source/ThirdParty/FreeType/include/freetype/tttables.h b/Source/ThirdParty/FreeType/include/freetype/tttables.h index 1c075dcf66..58312044ca 100644 --- a/Source/ThirdParty/FreeType/include/freetype/tttables.h +++ b/Source/ThirdParty/FreeType/include/freetype/tttables.h @@ -5,7 +5,7 @@ /* Basic SFNT/TrueType tables definitions and interface */ /* (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -45,8 +45,9 @@ FT_BEGIN_HEADER /* TrueType specific table types and functions. */ /* */ /* <Description> */ - /* This section contains the definition of TrueType-specific tables */ - /* as well as some routines used to access and process them. */ + /* This section contains definitions of some basic tables specific to */ + /* TrueType and OpenType as well as some routines used to access and */ + /* process them. */ /* */ /* <Order> */ /* TT_Header */ @@ -76,8 +77,8 @@ FT_BEGIN_HEADER /* TT_Header */ /* */ /* <Description> */ - /* A structure used to model a TrueType font header table. All */ - /* fields follow the TrueType specification. */ + /* A structure to model a TrueType font header table. All fields */ + /* follow the OpenType specification. */ /* */ typedef struct TT_Header_ { @@ -114,9 +115,9 @@ FT_BEGIN_HEADER /* TT_HoriHeader */ /* */ /* <Description> */ - /* A structure used to model a TrueType horizontal header, the `hhea' */ + /* A structure to model a TrueType horizontal header, the `hhea' */ /* table, as well as the corresponding horizontal metrics table, */ - /* i.e., the `hmtx' table. */ + /* `hmtx'. */ /* */ /* <Fields> */ /* Version :: The table version. */ @@ -131,7 +132,7 @@ FT_BEGIN_HEADER /* glyphs found in the font (maybe ASCII). */ /* */ /* You should use the `sTypoAscender' field */ - /* of the OS/2 table instead if you want */ + /* of the `OS/2' table instead if you want */ /* the correct one. */ /* */ /* Descender :: The font's descender, i.e., the distance */ @@ -145,7 +146,7 @@ FT_BEGIN_HEADER /* glyphs found in the font (maybe ASCII). */ /* */ /* You should use the `sTypoDescender' */ - /* field of the OS/2 table instead if you */ + /* field of the `OS/2' table instead if you */ /* want the correct one. */ /* */ /* Line_Gap :: The font's line gap, i.e., the distance */ @@ -175,6 +176,8 @@ FT_BEGIN_HEADER /* caret_Slope_Run :: The run coefficient of the cursor's */ /* slope. */ /* */ + /* caret_Offset :: The cursor's offset for slanted fonts. */ + /* */ /* Reserved :: 8~reserved bytes. */ /* */ /* metric_Data_Format :: Always~0. */ @@ -188,13 +191,10 @@ FT_BEGIN_HEADER /* short_metrics :: A pointer into the `hmtx' table. */ /* */ /* <Note> */ - /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ - /* be identical except for the names of their fields, */ - /* which are different. */ - /* */ - /* This ensures that a single function in the `ttload' */ - /* module is able to read both the horizontal and vertical */ - /* headers. */ + /* For an OpenType variation font, the values of the following fields */ + /* can change after a call to @FT_Set_Var_Design_Coordinates (and */ + /* friends) if the font contains an `MVAR' table: `caret_Slope_Rise', */ + /* `caret_Slope_Run', and `caret_Offset'. */ /* */ typedef struct TT_HoriHeader_ { @@ -217,9 +217,9 @@ FT_BEGIN_HEADER FT_Short metric_Data_Format; FT_UShort number_Of_HMetrics; - /* The following fields are not defined by the TrueType specification */ + /* The following fields are not defined by the OpenType specification */ /* but they are used to connect the metrics header to the relevant */ - /* `HMTX' table. */ + /* `hmtx' table. */ void* long_metrics; void* short_metrics; @@ -234,8 +234,8 @@ FT_BEGIN_HEADER /* */ /* <Description> */ /* A structure used to model a TrueType vertical header, the `vhea' */ - /* table, as well as the corresponding vertical metrics table, i.e., */ - /* the `vmtx' table. */ + /* table, as well as the corresponding vertical metrics table, */ + /* `vmtx'. */ /* */ /* <Fields> */ /* Version :: The table version. */ @@ -251,8 +251,8 @@ FT_BEGIN_HEADER /* ASCII). */ /* */ /* You should use the `sTypoAscender' */ - /* field of the OS/2 table instead if you */ - /* want the correct one. */ + /* field of the `OS/2' table instead if */ + /* you want the correct one. */ /* */ /* Descender :: The font's descender, i.e., the */ /* distance from the baseline to the */ @@ -266,8 +266,8 @@ FT_BEGIN_HEADER /* ASCII). */ /* */ /* You should use the `sTypoDescender' */ - /* field of the OS/2 table instead if you */ - /* want the correct one. */ + /* field of the `OS/2' table instead if */ + /* you want the correct one. */ /* */ /* Line_Gap :: The font's line gap, i.e., the distance */ /* to add to the ascender and descender to */ @@ -297,30 +297,26 @@ FT_BEGIN_HEADER /* slope. */ /* */ /* caret_Offset :: The cursor's offset for slanted fonts. */ - /* This value is `reserved' in vmtx */ - /* version 1.0. */ /* */ /* Reserved :: 8~reserved bytes. */ /* */ /* metric_Data_Format :: Always~0. */ /* */ - /* number_Of_HMetrics :: Number of VMetrics entries in the */ + /* number_Of_VMetrics :: Number of VMetrics entries in the */ /* `vmtx' table -- this value can be */ /* smaller than the total number of glyphs */ /* in the font. */ /* */ - /* long_metrics :: A pointer into the `vmtx' table. */ + /* long_metrics :: A pointer into the `vmtx' table. */ /* */ - /* short_metrics :: A pointer into the `vmtx' table. */ + /* short_metrics :: A pointer into the `vmtx' table. */ /* */ /* <Note> */ - /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ - /* be identical except for the names of their fields, */ - /* which are different. */ - /* */ - /* This ensures that a single function in the `ttload' */ - /* module is able to read both the horizontal and vertical */ - /* headers. */ + /* For an OpenType variation font, the values of the following fields */ + /* can change after a call to @FT_Set_Var_Design_Coordinates (and */ + /* friends) if the font contains an `MVAR' table: `Ascender', */ + /* `Descender', `Line_Gap', `caret_Slope_Rise', `caret_Slope_Run', */ + /* and `caret_Offset'. */ /* */ typedef struct TT_VertHeader_ { @@ -331,9 +327,9 @@ FT_BEGIN_HEADER FT_UShort advance_Height_Max; /* advance height maximum */ - FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ - FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ - FT_Short yMax_Extent; /* xmax or ymax extents */ + FT_Short min_Top_Side_Bearing; /* minimum top-sb */ + FT_Short min_Bottom_Side_Bearing; /* minimum bottom-sb */ + FT_Short yMax_Extent; /* ymax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; @@ -343,9 +339,9 @@ FT_BEGIN_HEADER FT_Short metric_Data_Format; FT_UShort number_Of_VMetrics; - /* The following fields are not defined by the TrueType specification */ - /* but they're used to connect the metrics header to the relevant */ - /* `HMTX' or `VMTX' table. */ + /* The following fields are not defined by the OpenType specification */ + /* but they are used to connect the metrics header to the relevant */ + /* `vmtx' table. */ void* long_metrics; void* short_metrics; @@ -359,12 +355,28 @@ FT_BEGIN_HEADER /* TT_OS2 */ /* */ /* <Description> */ - /* A structure used to model a TrueType OS/2 table. All fields */ - /* comply to the OpenType specification. */ + /* A structure to model a TrueType `OS/2' table. All fields comply */ + /* to the OpenType specification. */ + /* */ + /* Note that we now support old Mac fonts that do not include an */ + /* `OS/2' table. In this case, the `version' field is always set to */ + /* 0xFFFF. */ /* */ - /* Note that we now support old Mac fonts that do not include an OS/2 */ - /* table. In this case, the `version' field is always set to 0xFFFF. */ + /* <Note> */ + /* For an OpenType variation font, the values of the following fields */ + /* can change after a call to @FT_Set_Var_Design_Coordinates (and */ + /* friends) if the font contains an `MVAR' table: `sCapHeight', */ + /* `sTypoAscender', `sTypoDescender', `sTypoLineGap', `sxHeight', */ + /* `usWinAscent', `usWinDescent', `yStrikeoutPosition', */ + /* `yStrikeoutSize', `ySubscriptXOffset', `ySubScriptXSize', */ + /* `ySubscriptYOffset', `ySubscriptYSize', `ySuperscriptXOffset', */ + /* `ySuperscriptXSize', `ySuperscriptYOffset', and */ + /* `ySuperscriptYSize'. */ + /* */ + /* Possible values for bits in the `ulUnicodeRangeX' fields are given */ + /* by the @TT_UCR_XXX macros. */ /* */ + typedef struct TT_OS2_ { FT_UShort version; /* 0x0001 - more or 0xFFFF */ @@ -429,10 +441,16 @@ FT_BEGIN_HEADER /* TT_Postscript */ /* */ /* <Description> */ - /* A structure used to model a TrueType PostScript table. All fields */ - /* comply to the TrueType specification. This structure does not */ - /* reference the PostScript glyph names, which can be nevertheless */ - /* accessed with the `ttpost' module. */ + /* A structure to model a TrueType `post' table. All fields comply */ + /* to the OpenType specification. This structure does not reference */ + /* a font's PostScript glyph names; use @FT_Get_Glyph_Name to */ + /* retrieve them. */ + /* */ + /* <Note> */ + /* For an OpenType variation font, the values of the following fields */ + /* can change after a call to @FT_Set_Var_Design_Coordinates (and */ + /* friends) if the font contains an `MVAR' table: `underlinePosition' */ + /* and `underlineThickness'. */ /* */ typedef struct TT_Postscript_ { @@ -446,8 +464,8 @@ FT_BEGIN_HEADER FT_ULong minMemType1; FT_ULong maxMemType1; - /* Glyph names follow in the file, but we don't */ - /* load them by default. See the ttpost.c file. */ + /* Glyph names follow in the `post' table, but we don't */ + /* load them by default. */ } TT_Postscript; @@ -458,8 +476,8 @@ FT_BEGIN_HEADER /* TT_PCLT */ /* */ /* <Description> */ - /* A structure used to model a TrueType PCLT table. All fields */ - /* comply to the TrueType specification. */ + /* A structure to model a TrueType `PCLT' table. All fields comply */ + /* to the OpenType specification. */ /* */ typedef struct TT_PCLT_ { @@ -488,9 +506,9 @@ FT_BEGIN_HEADER /* TT_MaxProfile */ /* */ /* <Description> */ - /* The maximum profile is a table containing many max values, which */ - /* can be used to pre-allocate arrays. This ensures that no memory */ - /* allocation occurs during a glyph load. */ + /* The maximum profile (`maxp') table contains many max values, which */ + /* can be used to pre-allocate arrays for speeding up glyph loading */ + /* and hinting. */ /* */ /* <Fields> */ /* version :: The version number. */ @@ -500,21 +518,19 @@ FT_BEGIN_HEADER /* */ /* maxPoints :: The maximum number of points in a */ /* non-composite TrueType glyph. See also */ - /* the structure element */ /* `maxCompositePoints'. */ /* */ /* maxContours :: The maximum number of contours in a */ /* non-composite TrueType glyph. See also */ - /* the structure element */ /* `maxCompositeContours'. */ /* */ /* maxCompositePoints :: The maximum number of points in a */ - /* composite TrueType glyph. See also the */ - /* structure element `maxPoints'. */ + /* composite TrueType glyph. See also */ + /* `maxPoints'. */ /* */ /* maxCompositeContours :: The maximum number of contours in a */ - /* composite TrueType glyph. See also the */ - /* structure element `maxContours'. */ + /* composite TrueType glyph. See also */ + /* `maxContours'. */ /* */ /* maxZones :: The maximum number of zones used for */ /* glyph hinting. */ @@ -575,8 +591,9 @@ FT_BEGIN_HEADER /* FT_Sfnt_Tag */ /* */ /* <Description> */ - /* An enumeration used to specify the index of an SFNT table. */ - /* Used in the @FT_Get_Sfnt_Table API function. */ + /* An enumeration to specify indices of SFNT tables loaded and parsed */ + /* by FreeType during initialization of an SFNT font. Used in the */ + /* @FT_Get_Sfnt_Table API function. */ /* */ /* <Values> */ /* FT_SFNT_HEAD :: To access the font's @TT_Header structure. */ @@ -624,7 +641,7 @@ FT_BEGIN_HEADER /* FT_Get_Sfnt_Table */ /* */ /* <Description> */ - /* Return a pointer to a given SFNT table within a face. */ + /* Return a pointer to a given SFNT table stored within a face. */ /* */ /* <Input> */ /* face :: A handle to the source. */ @@ -632,7 +649,7 @@ FT_BEGIN_HEADER /* tag :: The index of the SFNT table. */ /* */ /* <Return> */ - /* A type-less pointer to the table. This will be~0 in case of */ + /* A type-less pointer to the table. This will be NULL in case of */ /* error, or if the corresponding table was not found *OR* loaded */ /* from the file. */ /* */ @@ -661,70 +678,70 @@ FT_BEGIN_HEADER FT_Sfnt_Tag tag ); - /************************************************************************** - * - * @function: - * FT_Load_Sfnt_Table - * - * @description: - * Load any font table into client memory. - * - * @input: - * face :: - * A handle to the source face. - * - * tag :: - * The four-byte tag of the table to load. Use the value~0 if you want - * to access the whole font file. Otherwise, you can use one of the - * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new - * one with @FT_MAKE_TAG. - * - * offset :: - * The starting offset in the table (or file if tag == 0). - * - * @output: - * buffer :: - * The target buffer address. The client must ensure that the memory - * array is big enough to hold the data. - * - * @inout: - * length :: - * If the `length' parameter is NULL, then try to load the whole table. - * Return an error code if it fails. - * - * Else, if `*length' is~0, exit immediately while returning the - * table's (or file) full size in it. - * - * Else the number of bytes to read from the table or file, from the - * starting offset. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If you need to determine the table's length you should first call this - * function with `*length' set to~0, as in the following example: - * - * { - * FT_ULong length = 0; - * - * - * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); - * if ( error ) { ... table does not exist ... } - * - * buffer = malloc( length ); - * if ( buffer == NULL ) { ... not enough memory ... } - * - * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); - * if ( error ) { ... could not load table ... } - * } - * - * Note that structures like @TT_Header or @TT_OS2 can't be used with - * this function; they are limited to @FT_Get_Sfnt_Table. Reason is that - * those structures depend on the processor architecture, with varying - * size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian). - * - */ + /************************************************************************** + * + * @function: + * FT_Load_Sfnt_Table + * + * @description: + * Load any SFNT font table into client memory. + * + * @input: + * face :: + * A handle to the source face. + * + * tag :: + * The four-byte tag of the table to load. Use value~0 if you want + * to access the whole font file. Otherwise, you can use one of the + * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new + * one with @FT_MAKE_TAG. + * + * offset :: + * The starting offset in the table (or file if tag~==~0). + * + * @output: + * buffer :: + * The target buffer address. The client must ensure that the memory + * array is big enough to hold the data. + * + * @inout: + * length :: + * If the `length' parameter is NULL, try to load the whole table. + * Return an error code if it fails. + * + * Else, if `*length' is~0, exit immediately while returning the + * table's (or file) full size in it. + * + * Else the number of bytes to read from the table or file, from the + * starting offset. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * If you need to determine the table's length you should first call this + * function with `*length' set to~0, as in the following example: + * + * { + * FT_ULong length = 0; + * + * + * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); + * if ( error ) { ... table does not exist ... } + * + * buffer = malloc( length ); + * if ( buffer == NULL ) { ... not enough memory ... } + * + * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); + * if ( error ) { ... could not load table ... } + * } + * + * Note that structures like @TT_Header or @TT_OS2 can't be used with + * this function; they are limited to @FT_Get_Sfnt_Table. Reason is that + * those structures depend on the processor architecture, with varying + * size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian). + * + */ FT_EXPORT( FT_Error ) FT_Load_Sfnt_Table( FT_Face face, FT_ULong tag, @@ -733,41 +750,41 @@ FT_BEGIN_HEADER FT_ULong* length ); - /************************************************************************** - * - * @function: - * FT_Sfnt_Table_Info - * - * @description: - * Return information on an SFNT table. - * - * @input: - * face :: - * A handle to the source face. - * - * table_index :: - * The index of an SFNT table. The function returns - * FT_Err_Table_Missing for an invalid value. - * - * @inout: - * tag :: - * The name tag of the SFNT table. If the value is NULL, `table_index' - * is ignored, and `length' returns the number of SFNT tables in the - * font. - * - * @output: - * length :: - * The length of the SFNT table (or the number of SFNT tables, depending - * on `tag'). - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * While parsing fonts, FreeType handles SFNT tables with length zero as - * missing. - * - */ + /************************************************************************** + * + * @function: + * FT_Sfnt_Table_Info + * + * @description: + * Return information on an SFNT table. + * + * @input: + * face :: + * A handle to the source face. + * + * table_index :: + * The index of an SFNT table. The function returns + * FT_Err_Table_Missing for an invalid value. + * + * @inout: + * tag :: + * The name tag of the SFNT table. If the value is NULL, `table_index' + * is ignored, and `length' returns the number of SFNT tables in the + * font. + * + * @output: + * length :: + * The length of the SFNT table (or the number of SFNT tables, depending + * on `tag'). + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * While parsing fonts, FreeType handles SFNT tables with length zero as + * missing. + * + */ FT_EXPORT( FT_Error ) FT_Sfnt_Table_Info( FT_Face face, FT_UInt table_index, @@ -781,16 +798,16 @@ FT_BEGIN_HEADER /* FT_Get_CMap_Language_ID */ /* */ /* <Description> */ - /* Return TrueType/sfnt specific cmap language ID. Definitions of */ - /* language ID values are in `ttnameid.h'. */ + /* Return cmap language ID as specified in the OpenType standard. */ + /* Definitions of language ID values are in file @FT_TRUETYPE_IDS_H. */ /* */ /* <Input> */ /* charmap :: */ /* The target charmap. */ /* */ /* <Return> */ - /* The language ID of `charmap'. If `charmap' doesn't belong to a */ - /* TrueType/sfnt face, just return~0 as the default value. */ + /* The language ID of `charmap'. If `charmap' doesn't belong to an */ + /* SFNT face, just return~0 as the default value. */ /* */ /* For a format~14 cmap (to access Unicode IVS), the return value is */ /* 0xFFFFFFFF. */ @@ -805,15 +822,15 @@ FT_BEGIN_HEADER /* FT_Get_CMap_Format */ /* */ /* <Description> */ - /* Return TrueType/sfnt specific cmap format. */ + /* Return the format of an SFNT `cmap' table. */ /* */ /* <Input> */ /* charmap :: */ /* The target charmap. */ /* */ /* <Return> */ - /* The format of `charmap'. If `charmap' doesn't belong to a */ - /* TrueType/sfnt face, return -1. */ + /* The format of `charmap'. If `charmap' doesn't belong to an SFNT */ + /* face, return -1. */ /* */ FT_EXPORT( FT_Long ) FT_Get_CMap_Format( FT_CharMap charmap ); diff --git a/Source/ThirdParty/FreeType/include/freetype/tttags.h b/Source/ThirdParty/FreeType/include/freetype/tttags.h index 63f6258e8a..32eb2fdc26 100644 --- a/Source/ThirdParty/FreeType/include/freetype/tttags.h +++ b/Source/ThirdParty/FreeType/include/freetype/tttags.h @@ -4,7 +4,7 @@ /* */ /* Tags for TrueType and OpenType tables (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/include/freetype/ttunpat.h b/Source/ThirdParty/FreeType/include/freetype/ttunpat.h index ca4676baf8..f5e417089e 100644 --- a/Source/ThirdParty/FreeType/include/freetype/ttunpat.h +++ b/Source/ThirdParty/FreeType/include/freetype/ttunpat.h @@ -3,9 +3,9 @@ /* ttunpat.h */ /* */ /* Definitions for the unpatented TrueType hinting system. */ -/* Obsolete, retained for backwards compatibility. */ +/* Obsolete, retained for backward compatibility. */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Written by Graham Asher <graham.asher@btinternet.com> */ diff --git a/Source/ThirdParty/FreeType/include/ft2build.h b/Source/ThirdParty/FreeType/include/ft2build.h index c89cb469e9..e7d808f3f4 100644 --- a/Source/ThirdParty/FreeType/include/ft2build.h +++ b/Source/ThirdParty/FreeType/include/ft2build.h @@ -4,7 +4,7 @@ /* */ /* FreeType 2 build and setup macros. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afangles.c b/Source/ThirdParty/FreeType/src/autofit/afangles.c index b856e57a8b..ccdae84136 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afangles.c +++ b/Source/ThirdParty/FreeType/src/autofit/afangles.c @@ -5,7 +5,7 @@ /* Routines used to compute vector angles with limited accuracy */ /* and very high speed. It also contains sorting routines (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afblue.c b/Source/ThirdParty/FreeType/src/autofit/afblue.c index 7719c02caa..a00c3a0765 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afblue.c +++ b/Source/ThirdParty/FreeType/src/autofit/afblue.c @@ -7,7 +7,7 @@ /* */ /* Auto-fitter data for blue strings (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -26,6 +26,14 @@ af_blue_strings[] = { /* */ + '\xF0', '\x9E', '\xA4', '\x8C', ' ', '\xF0', '\x9E', '\xA4', '\x85', ' ', '\xF0', '\x9E', '\xA4', '\x88', ' ', '\xF0', '\x9E', '\xA4', '\x8F', ' ', '\xF0', '\x9E', '\xA4', '\x94', ' ', '\xF0', '\x9E', '\xA4', '\x9A', /* 𞤌 𞤅 𞤈 𞤏 𞤔 𞤚 */ + '\0', + '\xF0', '\x9E', '\xA4', '\x82', ' ', '\xF0', '\x9E', '\xA4', '\x96', /* 𞤂 𞤖 */ + '\0', + '\xF0', '\x9E', '\xA4', '\xAC', ' ', '\xF0', '\x9E', '\xA4', '\xAE', ' ', '\xF0', '\x9E', '\xA4', '\xBB', ' ', '\xF0', '\x9E', '\xA4', '\xBC', ' ', '\xF0', '\x9E', '\xA4', '\xBE', /* 𞤬 𞤮 𞤻 𞤼 𞤾 */ + '\0', + '\xF0', '\x9E', '\xA4', '\xA4', ' ', '\xF0', '\x9E', '\xA4', '\xA8', ' ', '\xF0', '\x9E', '\xA4', '\xA9', ' ', '\xF0', '\x9E', '\xA4', '\xAD', ' ', '\xF0', '\x9E', '\xA4', '\xB4', ' ', '\xF0', '\x9E', '\xA4', '\xB8', ' ', '\xF0', '\x9E', '\xA4', '\xBA', ' ', '\xF0', '\x9E', '\xA5', '\x80', /* 𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀 */ + '\0', '\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', /* ا إ ل ك ط ظ */ '\0', '\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83', /* ت ث ط ظ ك */ @@ -44,12 +52,50 @@ '\0', '\xD5', '\xA2', ' ', '\xD5', '\xA8', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xAC', ' ', '\xD5', '\xB2', ' ', '\xD5', '\xBA', ' ', '\xD6', '\x83', ' ', '\xD6', '\x81', /* բ ը ի լ ղ պ փ ց */ '\0', + '\xF0', '\x90', '\xAC', '\x80', ' ', '\xF0', '\x90', '\xAC', '\x81', ' ', '\xF0', '\x90', '\xAC', '\x90', ' ', '\xF0', '\x90', '\xAC', '\x9B', /* 𐬀 𐬁 𐬐 𐬛 */ + '\0', + '\xF0', '\x90', '\xAC', '\x80', ' ', '\xF0', '\x90', '\xAC', '\x81', /* 𐬀 𐬁 */ + '\0', + '\xEA', '\x9A', '\xA7', ' ', '\xEA', '\x9A', '\xA8', ' ', '\xEA', '\x9B', '\x9B', ' ', '\xEA', '\x9B', '\x89', ' ', '\xEA', '\x9B', '\x81', ' ', '\xEA', '\x9B', '\x88', ' ', '\xEA', '\x9B', '\xAB', ' ', '\xEA', '\x9B', '\xAF', /* ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ ꛫ ꛯ */ + '\0', + '\xEA', '\x9A', '\xAD', ' ', '\xEA', '\x9A', '\xB3', ' ', '\xEA', '\x9A', '\xB6', ' ', '\xEA', '\x9B', '\xAC', ' ', '\xEA', '\x9A', '\xA2', ' ', '\xEA', '\x9A', '\xBD', ' ', '\xEA', '\x9B', '\xAF', ' ', '\xEA', '\x9B', '\xB2', /* ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲ */ + '\0', '\xE0', '\xA6', '\x85', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xAD', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95', /* অ ড ত ন ব ভ ল ক */ '\0', '\xE0', '\xA6', '\x87', ' ', '\xE0', '\xA6', '\x9F', ' ', '\xE0', '\xA6', '\xA0', ' ', '\xE0', '\xA6', '\xBF', ' ', '\xE0', '\xA7', '\x80', ' ', '\xE0', '\xA7', '\x88', ' ', '\xE0', '\xA7', '\x97', /* ই ট ঠ ি ী ৈ ৗ */ '\0', '\xE0', '\xA6', '\x93', ' ', '\xE0', '\xA6', '\x8F', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95', /* ও এ ড ত ন ব ল ক */ '\0', + '\xE1', '\x9D', '\x90', ' ', '\xE1', '\x9D', '\x88', /* ᝐ ᝈ */ + '\0', + '\xE1', '\x9D', '\x85', ' ', '\xE1', '\x9D', '\x8A', ' ', '\xE1', '\x9D', '\x8E', /* ᝅ ᝊ ᝎ */ + '\0', + '\xE1', '\x9D', '\x82', ' ', '\xE1', '\x9D', '\x83', ' ', '\xE1', '\x9D', '\x89', ' ', '\xE1', '\x9D', '\x8C', /* ᝂ ᝃ ᝉ ᝌ */ + '\0', + '\xE1', '\x9D', '\x80', ' ', '\xE1', '\x9D', '\x83', ' ', '\xE1', '\x9D', '\x86', ' ', '\xE1', '\x9D', '\x89', ' ', '\xE1', '\x9D', '\x8B', ' ', '\xE1', '\x9D', '\x8F', ' ', '\xE1', '\x9D', '\x91', /* ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ */ + '\0', + '\xE1', '\x97', '\x9C', ' ', '\xE1', '\x96', '\xB4', ' ', '\xE1', '\x90', '\x81', ' ', '\xE1', '\x92', '\xA3', ' ', '\xE1', '\x91', '\xAB', ' ', '\xE1', '\x91', '\x8E', ' ', '\xE1', '\x94', '\x91', ' ', '\xE1', '\x97', '\xB0', /* ᗜ ᖴ ᐁ ᒣ ᑫ ᑎ ᔑ ᗰ */ + '\0', + '\xE1', '\x97', '\xB6', ' ', '\xE1', '\x96', '\xB5', ' ', '\xE1', '\x92', '\xA7', ' ', '\xE1', '\x90', '\x83', ' ', '\xE1', '\x91', '\x8C', ' ', '\xE1', '\x92', '\x8D', ' ', '\xE1', '\x94', '\x91', ' ', '\xE1', '\x97', '\xA2', /* ᗶ ᖵ ᒧ ᐃ ᑌ ᒍ ᔑ ᗢ */ + '\0', + '\xE1', '\x93', '\x93', ' ', '\xE1', '\x93', '\x95', ' ', '\xE1', '\x93', '\x80', ' ', '\xE1', '\x93', '\x82', ' ', '\xE1', '\x93', '\x84', ' ', '\xE1', '\x95', '\x84', ' ', '\xE1', '\x95', '\x86', ' ', '\xE1', '\x98', '\xA3', /* ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ */ + '\0', + '\xE1', '\x95', '\x83', ' ', '\xE1', '\x93', '\x82', ' ', '\xE1', '\x93', '\x80', ' ', '\xE1', '\x95', '\x82', ' ', '\xE1', '\x93', '\x97', ' ', '\xE1', '\x93', '\x9A', ' ', '\xE1', '\x95', '\x86', ' ', '\xE1', '\x98', '\xA3', /* ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ */ + '\0', + '\xE1', '\x90', '\xAA', ' ', '\xE1', '\x99', '\x86', ' ', '\xE1', '\xA3', '\x98', ' ', '\xE1', '\x90', '\xA2', ' ', '\xE1', '\x92', '\xBE', ' ', '\xE1', '\xA3', '\x97', ' ', '\xE1', '\x94', '\x86', /* ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ */ + '\0', + '\xE1', '\x99', '\x86', ' ', '\xE1', '\x97', '\xAE', ' ', '\xE1', '\x92', '\xBB', ' ', '\xE1', '\x90', '\x9E', ' ', '\xE1', '\x94', '\x86', ' ', '\xE1', '\x92', '\xA1', ' ', '\xE1', '\x92', '\xA2', ' ', '\xE1', '\x93', '\x91', /* ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ */ + '\0', + '\xF0', '\x90', '\x8A', '\xA7', ' ', '\xF0', '\x90', '\x8A', '\xAB', ' ', '\xF0', '\x90', '\x8A', '\xAC', ' ', '\xF0', '\x90', '\x8A', '\xAD', ' ', '\xF0', '\x90', '\x8A', '\xB1', ' ', '\xF0', '\x90', '\x8A', '\xBA', ' ', '\xF0', '\x90', '\x8A', '\xBC', ' ', '\xF0', '\x90', '\x8A', '\xBF', /* 𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿 */ + '\0', + '\xF0', '\x90', '\x8A', '\xA3', ' ', '\xF0', '\x90', '\x8A', '\xA7', ' ', '\xF0', '\x90', '\x8A', '\xB7', ' ', '\xF0', '\x90', '\x8B', '\x80', ' ', '\xF0', '\x90', '\x8A', '\xAB', ' ', '\xF0', '\x90', '\x8A', '\xB8', ' ', '\xF0', '\x90', '\x8B', '\x89', /* 𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉 */ + '\0', + '\xF0', '\x91', '\x84', '\x83', ' ', '\xF0', '\x91', '\x84', '\x85', ' ', '\xF0', '\x91', '\x84', '\x89', ' ', '\xF0', '\x91', '\x84', '\x99', ' ', '\xF0', '\x91', '\x84', '\x97', /* 𑄃 𑄅 𑄉 𑄙 𑄗 */ + '\0', + '\xF0', '\x91', '\x84', '\x85', ' ', '\xF0', '\x91', '\x84', '\x9B', ' ', '\xF0', '\x91', '\x84', '\x9D', ' ', '\xF0', '\x91', '\x84', '\x97', ' ', '\xF0', '\x91', '\x84', '\x93', /* 𑄅 𑄛 𑄝 𑄗 𑄓 */ + '\0', + '\xF0', '\x91', '\x84', '\x96', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\x98', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\x99', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\xA4', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\xA5', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', /* 𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢 */ + '\0', '\xE1', '\x8F', '\x86', ' ', '\xE1', '\x8E', '\xBB', ' ', '\xE1', '\x8E', '\xAC', ' ', '\xE1', '\x8F', '\x83', ' ', '\xE1', '\x8E', '\xA4', ' ', '\xE1', '\x8F', '\xA3', ' ', '\xE1', '\x8E', '\xA6', ' ', '\xE1', '\x8F', '\x95', /* Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ */ '\0', '\xEA', '\xAE', '\x92', ' ', '\xEA', '\xAE', '\xA4', ' ', '\xEA', '\xAE', '\xB6', ' ', '\xEA', '\xAD', '\xB4', ' ', '\xEA', '\xAD', '\xBE', ' ', '\xEA', '\xAE', '\x97', ' ', '\xEA', '\xAE', '\x9D', ' ', '\xEA', '\xAE', '\xBF', /* ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ */ @@ -58,6 +104,20 @@ '\0', '\xE1', '\x8F', '\xB8', ' ', '\xEA', '\xAE', '\x90', ' ', '\xEA', '\xAD', '\xB9', ' ', '\xEA', '\xAD', '\xBB', /* ᏸ ꮐ ꭹ ꭻ */ '\0', + '\xE2', '\xB2', '\x8C', ' ', '\xE2', '\xB2', '\x8E', ' ', '\xE2', '\xB2', '\xA0', ' ', '\xE2', '\xB3', '\x9E', ' ', '\xE2', '\xB2', '\x9E', ' ', '\xE2', '\xB2', '\x90', ' ', '\xE2', '\xB2', '\xA4', ' ', '\xE2', '\xB3', '\x8A', /* Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ Ⲑ Ⲥ Ⳋ */ + '\0', + '\xE2', '\xB3', '\x90', ' ', '\xE2', '\xB3', '\x98', ' ', '\xE2', '\xB3', '\x9E', ' ', '\xE2', '\xB2', '\x8E', ' ', '\xE2', '\xB2', '\x9E', ' ', '\xE2', '\xB2', '\x90', ' ', '\xE2', '\xB3', '\x9C', ' ', '\xE2', '\xB2', '\xB0', /* Ⳑ Ⳙ Ⳟ Ⲏ Ⲟ Ⲑ Ⳝ Ⲱ */ + '\0', + '\xE2', '\xB2', '\x8D', ' ', '\xE2', '\xB2', '\x8F', ' ', '\xE2', '\xB2', '\xA1', ' ', '\xE2', '\xB3', '\x9F', ' ', '\xE2', '\xB2', '\x9F', ' ', '\xE2', '\xB2', '\x91', ' ', '\xE2', '\xB2', '\xA5', ' ', '\xE2', '\xB3', '\x8B', /* ⲍ ⲏ ⲡ ⳟ ⲟ ⲑ ⲥ ⳋ */ + '\0', + '\xE2', '\xB3', '\x91', ' ', '\xE2', '\xB3', '\x99', ' ', '\xE2', '\xB3', '\x9F', ' ', '\xE2', '\xB2', '\x8F', ' ', '\xE2', '\xB2', '\x9F', ' ', '\xE2', '\xB2', '\x91', ' ', '\xE2', '\xB3', '\x9D', ' ', '\xE2', '\xB3', '\x92', /* ⳑ ⳙ ⳟ ⲏ ⲟ ⲑ ⳝ Ⳓ */ + '\0', + '\xF0', '\x90', '\xA0', '\x8D', ' ', '\xF0', '\x90', '\xA0', '\x99', ' ', '\xF0', '\x90', '\xA0', '\xB3', ' ', '\xF0', '\x90', '\xA0', '\xB1', ' ', '\xF0', '\x90', '\xA0', '\x85', ' ', '\xF0', '\x90', '\xA0', '\x93', ' ', '\xF0', '\x90', '\xA0', '\xA3', ' ', '\xF0', '\x90', '\xA0', '\xA6', /* 𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦 */ + '\0', + '\xF0', '\x90', '\xA0', '\x83', ' ', '\xF0', '\x90', '\xA0', '\x8A', ' ', '\xF0', '\x90', '\xA0', '\x9B', ' ', '\xF0', '\x90', '\xA0', '\xA3', ' ', '\xF0', '\x90', '\xA0', '\xB3', ' ', '\xF0', '\x90', '\xA0', '\xB5', ' ', '\xF0', '\x90', '\xA0', '\x90', /* 𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐 */ + '\0', + '\xF0', '\x90', '\xA0', '\x88', ' ', '\xF0', '\x90', '\xA0', '\x8F', ' ', '\xF0', '\x90', '\xA0', '\x96', /* 𐠈 𐠏 𐠖 */ + '\0', '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е П З О С Э */ '\0', '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е Ш З О С Э */ @@ -66,6 +126,14 @@ '\0', '\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84', /* р у ф */ '\0', + '\xF0', '\x90', '\x90', '\x82', ' ', '\xF0', '\x90', '\x90', '\x84', ' ', '\xF0', '\x90', '\x90', '\x8B', ' ', '\xF0', '\x90', '\x90', '\x97', ' ', '\xF0', '\x90', '\x90', '\x91', /* 𐐂 𐐄 𐐋 𐐗 𐐑 */ + '\0', + '\xF0', '\x90', '\x90', '\x80', ' ', '\xF0', '\x90', '\x90', '\x82', ' ', '\xF0', '\x90', '\x90', '\x84', ' ', '\xF0', '\x90', '\x90', '\x97', ' ', '\xF0', '\x90', '\x90', '\x9B', /* 𐐀 𐐂 𐐄 𐐗 𐐛 */ + '\0', + '\xF0', '\x90', '\x90', '\xAA', ' ', '\xF0', '\x90', '\x90', '\xAC', ' ', '\xF0', '\x90', '\x90', '\xB3', ' ', '\xF0', '\x90', '\x90', '\xBF', ' ', '\xF0', '\x90', '\x90', '\xB9', /* 𐐪 𐐬 𐐳 𐐿 𐐹 */ + '\0', + '\xF0', '\x90', '\x90', '\xA8', ' ', '\xF0', '\x90', '\x90', '\xAA', ' ', '\xF0', '\x90', '\x90', '\xAC', ' ', '\xF0', '\x90', '\x90', '\xBF', ' ', '\xF0', '\x90', '\x91', '\x83', /* 𐐨 𐐪 𐐬 𐐿 𐑃 */ + '\0', '\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x85', ' ', '\xE0', '\xA4', '\x86', ' ', '\xE0', '\xA4', '\xA5', ' ', '\xE0', '\xA4', '\xA7', ' ', '\xE0', '\xA4', '\xAD', ' ', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */ '\0', '\xE0', '\xA4', '\x88', ' ', '\xE0', '\xA4', '\x90', ' ', '\xE0', '\xA4', '\x93', ' ', '\xE0', '\xA4', '\x94', ' ', '\xE0', '\xA4', '\xBF', ' ', '\xE0', '\xA5', '\x80', ' ', '\xE0', '\xA5', '\x8B', ' ', '\xE0', '\xA5', '\x8C', /* ई ऐ ओ औ ि ी ो ौ */ @@ -98,6 +166,18 @@ '\0', '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x98', ' ', '\xE2', '\xB4', '\x9D', /* ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ */ '\0', + '\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x94', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\xAB', ' ', '\xE2', '\xB0', '\x8B', /* Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ */ + '\0', + '\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x9E', ' ', '\xE2', '\xB0', '\xA1', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\x94', /* Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ */ + '\0', + '\xE2', '\xB0', '\xB5', ' ', '\xE2', '\xB1', '\x84', ' ', '\xE2', '\xB1', '\x9A', ' ', '\xE2', '\xB0', '\xB4', ' ', '\xE2', '\xB0', '\xB2', ' ', '\xE2', '\xB0', '\xBA', ' ', '\xE2', '\xB1', '\x9B', ' ', '\xE2', '\xB0', '\xBB', /* ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ */ + '\0', + '\xE2', '\xB0', '\xB5', ' ', '\xE2', '\xB0', '\xB4', ' ', '\xE2', '\xB0', '\xB2', ' ', '\xE2', '\xB1', '\x9A', ' ', '\xE2', '\xB1', '\x8E', ' ', '\xE2', '\xB1', '\x91', ' ', '\xE2', '\xB0', '\xBA', ' ', '\xE2', '\xB1', '\x84', /* ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ */ + '\0', + '\xF0', '\x90', '\x8C', '\xB2', ' ', '\xF0', '\x90', '\x8C', '\xB6', ' ', '\xF0', '\x90', '\x8D', '\x80', ' ', '\xF0', '\x90', '\x8D', '\x84', ' ', '\xF0', '\x90', '\x8C', '\xB4', ' ', '\xF0', '\x90', '\x8D', '\x83', ' ', '\xF0', '\x90', '\x8D', '\x88', ' ', '\xF0', '\x90', '\x8C', '\xBE', /* 𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾 */ + '\0', + '\xF0', '\x90', '\x8C', '\xB6', ' ', '\xF0', '\x90', '\x8C', '\xB4', ' ', '\xF0', '\x90', '\x8D', '\x83', ' ', '\xF0', '\x90', '\x8D', '\x88', /* 𐌶 𐌴 𐍃 𐍈 */ + '\0', '\xCE', '\x93', ' ', '\xCE', '\x92', ' ', '\xCE', '\x95', ' ', '\xCE', '\x96', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', ' ', '\xCE', '\xA9', /* Γ Β Ε Ζ Θ Ο Ω */ '\0', '\xCE', '\x92', ' ', '\xCE', '\x94', ' ', '\xCE', '\x96', ' ', '\xCE', '\x9E', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', /* Β Δ Ζ Ξ Θ Ο */ @@ -138,6 +218,16 @@ '\0', '\xE0', '\xB2', '\x85', ' ', '\xE0', '\xB2', '\x89', ' ', '\xE0', '\xB2', '\x8E', ' ', '\xE0', '\xB2', '\xB2', ' ', '\xE0', '\xB3', '\xA6', ' ', '\xE0', '\xB3', '\xA8', ' ', '\xE0', '\xB3', '\xAC', ' ', '\xE0', '\xB3', '\xAD', /* ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭ */ '\0', + '\xEA', '\xA4', '\x85', ' ', '\xEA', '\xA4', '\x8F', ' ', '\xEA', '\xA4', '\x81', ' ', '\xEA', '\xA4', '\x8B', ' ', '\xEA', '\xA4', '\x80', ' ', '\xEA', '\xA4', '\x8D', /* ꤅ ꤏ ꤁ ꤋ ꤀ ꤍ */ + '\0', + '\xEA', '\xA4', '\x88', ' ', '\xEA', '\xA4', '\x98', ' ', '\xEA', '\xA4', '\x80', ' ', '\xEA', '\xA4', '\x8D', ' ', '\xEA', '\xA4', '\xA2', /* ꤈ ꤘ ꤀ ꤍ ꤢ */ + '\0', + '\xEA', '\xA4', '\x96', ' ', '\xEA', '\xA4', '\xA1', /* ꤖ ꤡ */ + '\0', + '\xEA', '\xA4', '\x91', ' ', '\xEA', '\xA4', '\x9C', ' ', '\xEA', '\xA4', '\x9E', /* ꤑ ꤜ ꤞ */ + '\0', + '\xEA', '\xA4', '\x91', '\xEA', '\xA4', '\xAC', ' ', '\xEA', '\xA4', '\x9C', '\xEA', '\xA4', '\xAD', ' ', '\xEA', '\xA4', '\x94', '\xEA', '\xA4', '\xAC', /* ꤑ꤬ ꤜ꤭ ꤔ꤬ */ + '\0', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6', /* ខ ទ ន ឧ ឩ ា */ '\0', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90', /* ក្ក ក្ខ ក្គ ក្ថ */ @@ -168,7 +258,9 @@ '\0', 'f', ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'd', ' ', 'b', ' ', 'h', /* f i j k d b h */ '\0', - 'x', ' ', 'z', ' ', 'r', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* x z r o e s c */ + 'u', ' ', 'v', ' ', 'x', ' ', 'z', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* u v x z o e s c */ + '\0', + 'n', ' ', 'r', ' ', 'x', ' ', 'z', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* n r x z o e s c */ '\0', 'p', ' ', 'q', ' ', 'g', ' ', 'j', ' ', 'y', /* p q g j y */ '\0', @@ -192,6 +284,10 @@ '\0', '\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D', /* ᵖ ʸ ᵍ */ '\0', + '\xEA', '\x93', '\xA1', ' ', '\xEA', '\x93', '\xA7', ' ', '\xEA', '\x93', '\xB1', ' ', '\xEA', '\x93', '\xB6', ' ', '\xEA', '\x93', '\xA9', ' ', '\xEA', '\x93', '\x9A', ' ', '\xEA', '\x93', '\xB5', ' ', '\xEA', '\x93', '\xB3', /* ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ */ + '\0', + '\xEA', '\x93', '\x95', ' ', '\xEA', '\x93', '\x9C', ' ', '\xEA', '\x93', '\x9E', ' ', '\xEA', '\x93', '\xA1', ' ', '\xEA', '\x93', '\x9B', ' ', '\xEA', '\x93', '\xA2', ' ', '\xEA', '\x93', '\xB3', ' ', '\xEA', '\x93', '\xB4', /* ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ */ + '\0', '\xE0', '\xB4', '\x92', ' ', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xB1', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', ' ', '\xE0', '\xB4', '\x9A', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\xAA', /* ഒ ട ഠ റ ച പ ച്ച പ്പ */ '\0', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xA7', ' ', '\xE0', '\xB4', '\xB6', ' ', '\xE0', '\xB4', '\x98', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xA5', ' ', '\xE0', '\xB4', '\xB2', /* ട ഠ ധ ശ ഘ ച ഥ ല */ @@ -204,12 +300,68 @@ '\0', '\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89', /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */ '\0', + '\xDF', '\x90', ' ', '\xDF', '\x89', ' ', '\xDF', '\x92', ' ', '\xDF', '\x9F', ' ', '\xDF', '\x96', ' ', '\xDF', '\x9C', ' ', '\xDF', '\xA0', ' ', '\xDF', '\xA5', /* ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ */ + '\0', + '\xDF', '\x80', ' ', '\xDF', '\x98', ' ', '\xDF', '\xA1', ' ', '\xDF', '\xA0', ' ', '\xDF', '\xA5', /* ߀ ߘ ߡ ߠ ߥ */ + '\0', + '\xDF', '\x8F', ' ', '\xDF', '\x9B', ' ', '\xDF', '\x8B', /* ߏ ߛ ߋ */ + '\0', + '\xDF', '\x8E', ' ', '\xDF', '\x8F', ' ', '\xDF', '\x9B', ' ', '\xDF', '\x8B', /* ߎ ߏ ߛ ߋ */ + '\0', + '\xE1', '\xB1', '\x9B', ' ', '\xE1', '\xB1', '\x9C', ' ', '\xE1', '\xB1', '\x9D', ' ', '\xE1', '\xB1', '\xA1', ' ', '\xE1', '\xB1', '\xA2', ' ', '\xE1', '\xB1', '\xA5', /* ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ */ + '\0', + '\xF0', '\x90', '\xB0', '\x97', ' ', '\xF0', '\x90', '\xB0', '\x98', ' ', '\xF0', '\x90', '\xB0', '\xA7', /* 𐰗 𐰘 𐰧 */ + '\0', + '\xF0', '\x90', '\xB0', '\x89', ' ', '\xF0', '\x90', '\xB0', '\x97', ' ', '\xF0', '\x90', '\xB0', '\xA6', ' ', '\xF0', '\x90', '\xB0', '\xA7', /* 𐰉 𐰗 𐰦 𐰧 */ + '\0', + '\xF0', '\x90', '\x92', '\xBE', ' ', '\xF0', '\x90', '\x93', '\x8D', ' ', '\xF0', '\x90', '\x93', '\x92', ' ', '\xF0', '\x90', '\x93', '\x93', ' ', '\xF0', '\x90', '\x92', '\xBB', ' ', '\xF0', '\x90', '\x93', '\x82', ' ', '\xF0', '\x90', '\x92', '\xB5', ' ', '\xF0', '\x90', '\x93', '\x86', /* 𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆 */ + '\0', + '\xF0', '\x90', '\x92', '\xB0', ' ', '\xF0', '\x90', '\x93', '\x8D', ' ', '\xF0', '\x90', '\x93', '\x82', ' ', '\xF0', '\x90', '\x92', '\xBF', ' ', '\xF0', '\x90', '\x93', '\x8E', ' ', '\xF0', '\x90', '\x92', '\xB9', /* 𐒰 𐓍 𐓂 𐒿 𐓎 𐒹 */ + '\0', + '\xF0', '\x90', '\x92', '\xBC', ' ', '\xF0', '\x90', '\x92', '\xBD', ' ', '\xF0', '\x90', '\x92', '\xBE', /* 𐒼 𐒽 𐒾 */ + '\0', + '\xF0', '\x90', '\x93', '\xB5', ' ', '\xF0', '\x90', '\x93', '\xB6', ' ', '\xF0', '\x90', '\x93', '\xBA', ' ', '\xF0', '\x90', '\x93', '\xBB', ' ', '\xF0', '\x90', '\x93', '\x9D', ' ', '\xF0', '\x90', '\x93', '\xA3', ' ', '\xF0', '\x90', '\x93', '\xAA', ' ', '\xF0', '\x90', '\x93', '\xAE', /* 𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮 */ + '\0', + '\xF0', '\x90', '\x93', '\x98', ' ', '\xF0', '\x90', '\x93', '\x9A', ' ', '\xF0', '\x90', '\x93', '\xA3', ' ', '\xF0', '\x90', '\x93', '\xB5', ' ', '\xF0', '\x90', '\x93', '\xA1', ' ', '\xF0', '\x90', '\x93', '\xA7', ' ', '\xF0', '\x90', '\x93', '\xAA', ' ', '\xF0', '\x90', '\x93', '\xB6', /* 𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶 */ + '\0', + '\xF0', '\x90', '\x93', '\xA4', ' ', '\xF0', '\x90', '\x93', '\xA6', ' ', '\xF0', '\x90', '\x93', '\xB8', ' ', '\xF0', '\x90', '\x93', '\xB9', ' ', '\xF0', '\x90', '\x93', '\x9B', /* 𐓤 𐓦 𐓸 𐓹 𐓛 */ + '\0', + '\xF0', '\x90', '\x93', '\xA4', ' ', '\xF0', '\x90', '\x93', '\xA5', ' ', '\xF0', '\x90', '\x93', '\xA6', /* 𐓤 𐓥 𐓦 */ + '\0', + '\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x89', ' ', '\xF0', '\x90', '\x92', '\x90', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\x98', ' ', '\xF0', '\x90', '\x92', '\x9B', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA3', /* 𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣 */ + '\0', + '\xF0', '\x90', '\x92', '\x80', ' ', '\xF0', '\x90', '\x92', '\x82', ' ', '\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x88', ' ', '\xF0', '\x90', '\x92', '\x8A', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA9', /* 𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩 */ + '\0', + '\xEA', '\xA2', '\x9C', ' ', '\xEA', '\xA2', '\x9E', ' ', '\xEA', '\xA2', '\xB3', ' ', '\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\x96', ' ', '\xEA', '\xA2', '\x92', ' ', '\xEA', '\xA2', '\x9D', ' ', '\xEA', '\xA2', '\x9B', /* ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ */ + '\0', + '\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\xA8', ' ', '\xEA', '\xA2', '\xBA', ' ', '\xEA', '\xA2', '\xA4', ' ', '\xEA', '\xA2', '\x8E', /* ꢂ ꢨ ꢺ ꢤ ꢎ */ + '\0', + '\xF0', '\x90', '\x91', '\x95', ' ', '\xF0', '\x90', '\x91', '\x99', /* 𐑕 𐑙 */ + '\0', + '\xF0', '\x90', '\x91', '\x94', ' ', '\xF0', '\x90', '\x91', '\x96', ' ', '\xF0', '\x90', '\x91', '\x97', ' ', '\xF0', '\x90', '\x91', '\xB9', ' ', '\xF0', '\x90', '\x91', '\xBB', /* 𐑔 𐑖 𐑗 𐑹 𐑻 */ + '\0', + '\xF0', '\x90', '\x91', '\x9F', ' ', '\xF0', '\x90', '\x91', '\xA3', /* 𐑟 𐑣 */ + '\0', + '\xF0', '\x90', '\x91', '\xB1', ' ', '\xF0', '\x90', '\x91', '\xB2', ' ', '\xF0', '\x90', '\x91', '\xB3', ' ', '\xF0', '\x90', '\x91', '\xB4', ' ', '\xF0', '\x90', '\x91', '\xB8', ' ', '\xF0', '\x90', '\x91', '\xBA', ' ', '\xF0', '\x90', '\x91', '\xBC', /* 𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼 */ + '\0', + '\xF0', '\x90', '\x91', '\xB4', ' ', '\xF0', '\x90', '\x91', '\xBB', ' ', '\xF0', '\x90', '\x91', '\xB9', /* 𐑴 𐑻 𐑹 */ + '\0', '\xE0', '\xB6', '\x89', ' ', '\xE0', '\xB6', '\x9A', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\xB4', ' ', '\xE0', '\xB6', '\xBA', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB7', '\x86', /* ඉ ක ඝ ඳ ප ය ල ෆ */ '\0', '\xE0', '\xB6', '\x91', ' ', '\xE0', '\xB6', '\x94', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xA2', ' ', '\xE0', '\xB6', '\xA7', ' ', '\xE0', '\xB6', '\xAE', ' ', '\xE0', '\xB6', '\xB0', ' ', '\xE0', '\xB6', '\xBB', /* එ ඔ ඝ ජ ට ථ ධ ර */ '\0', '\xE0', '\xB6', '\xAF', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\x8B', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x96', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xB6', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xAF', '\xE0', '\xB7', '\x94', /* ද ඳ උ ල තූ තු බු දු */ '\0', + '\xE1', '\xAE', '\x8B', ' ', '\xE1', '\xAE', '\x9E', ' ', '\xE1', '\xAE', '\xAE', ' ', '\xE1', '\xAE', '\xBD', ' ', '\xE1', '\xAE', '\xB0', ' ', '\xE1', '\xAE', '\x88', /* ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ */ + '\0', + '\xE1', '\xAE', '\x84', ' ', '\xE1', '\xAE', '\x94', ' ', '\xE1', '\xAE', '\x95', ' ', '\xE1', '\xAE', '\x97', ' ', '\xE1', '\xAE', '\xB0', ' ', '\xE1', '\xAE', '\x86', ' ', '\xE1', '\xAE', '\x88', ' ', '\xE1', '\xAE', '\x89', /* ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ */ + '\0', + '\xE1', '\xAE', '\xBC', ' ', '\xE1', '\xB3', '\x84', /* ᮼ ᳄ */ + '\0', + '\xEA', '\xAA', '\x86', ' ', '\xEA', '\xAA', '\x94', ' ', '\xEA', '\xAA', '\x92', ' ', '\xEA', '\xAA', '\x96', ' ', '\xEA', '\xAA', '\xAB', /* ꪆ ꪔ ꪒ ꪖ ꪫ */ + '\0', + '\xEA', '\xAA', '\x89', ' ', '\xEA', '\xAA', '\xAB', ' ', '\xEA', '\xAA', '\xAE', /* ꪉ ꪫ ꪮ */ + '\0', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x92', ' ', '\xE0', '\xAE', '\x93', ' ', '\xE0', '\xAE', '\xB1', ' ', '\xE0', '\xAE', '\x88', ' ', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9A', /* உ ஒ ஓ ற ஈ க ங ச */ '\0', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x9A', ' ', '\xE0', '\xAE', '\xB2', ' ', '\xE0', '\xAE', '\xB6', ' ', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9F', ' ', '\xE0', '\xAE', '\xAA', /* க ச ல ஶ உ ங ட ப */ @@ -231,6 +383,12 @@ '\xE0', '\xB8', '\x8D', ' ', '\xE0', '\xB8', '\x90', /* ญ ฐ */ '\0', '\xE0', '\xB9', '\x90', ' ', '\xE0', '\xB9', '\x91', ' ', '\xE0', '\xB9', '\x93', /* ๐ ๑ ๓ */ + '\0', + '\xE2', '\xB5', '\x94', ' ', '\xE2', '\xB5', '\x99', ' ', '\xE2', '\xB5', '\x9B', ' ', '\xE2', '\xB5', '\x9E', ' ', '\xE2', '\xB4', '\xB5', ' ', '\xE2', '\xB4', '\xBC', ' ', '\xE2', '\xB4', '\xB9', ' ', '\xE2', '\xB5', '\x8E', /* ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ */ + '\0', + '\xEA', '\x97', '\x8D', ' ', '\xEA', '\x98', '\x96', ' ', '\xEA', '\x98', '\x99', ' ', '\xEA', '\x98', '\x9C', ' ', '\xEA', '\x96', '\x9C', ' ', '\xEA', '\x96', '\x9D', ' ', '\xEA', '\x94', '\x85', ' ', '\xEA', '\x95', '\xA2', /* ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ */ + '\0', + '\xEA', '\x97', '\x8D', ' ', '\xEA', '\x98', '\x96', ' ', '\xEA', '\x98', '\x99', ' ', '\xEA', '\x97', '\x9E', ' ', '\xEA', '\x94', '\x85', ' ', '\xEA', '\x95', '\xA2', ' ', '\xEA', '\x96', '\x9C', ' ', '\xEA', '\x94', '\x86', /* ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ */ #ifdef AF_CONFIG_OPTION_CJK '\0', '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 他 们 你 來 們 到 和 地 */ @@ -281,6 +439,12 @@ af_blue_stringsets[] = { /* */ + { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ARABIC_BOTTOM, 0 }, { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }, @@ -293,6 +457,12 @@ { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, 0 }, { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_AVESTAN_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_BAMUM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_BAMUM_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_BENGALI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP | @@ -300,6 +470,27 @@ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_BENGALI_BASE, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_BUHID_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_BUHID_LARGE, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_BUHID_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_BUHID_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CHAKMA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CHAKMA_BOTTOM, 0 }, + { AF_BLUE_STRING_CHAKMA_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CARIAN_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_CHEROKEE_CAPITAL, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CHEROKEE_CAPITAL, 0 }, { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, @@ -308,6 +499,17 @@ { AF_BLUE_STRING_CHEROKEE_SMALL, 0 }, { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 }, + { AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CYPRIOT_SMALL, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }, { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | @@ -323,6 +525,12 @@ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }, { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -340,6 +548,15 @@ { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GOTHIC_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 }, { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, @@ -368,6 +585,13 @@ { AF_BLUE_STRING_HEBREW_BOTTOM, 0 }, { AF_BLUE_STRING_HEBREW_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_KAYAH_LI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_KAYAH_LI_BOTTOM, 0 }, + { AF_BLUE_STRING_KAYAH_LI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 }, + { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_KANNADA_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -392,9 +616,9 @@ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }, { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | + { AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_LATIN_SMALL, 0 }, + { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 }, { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, @@ -413,6 +637,9 @@ { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }, { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_LISU_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -422,14 +649,55 @@ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_NKO_BOTTOM, 0 }, + { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OL_CHIKI, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 }, + { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSMANYA_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 }, + { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 }, + { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_SINHALA_BOTTOM, 0 }, { AF_BLUE_STRING_SINHALA_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_SUNDANESE_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SUNDANESE_BOTTOM, 0 }, + { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_TAMIL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_TAMIL_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_TAI_VIET_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_TELUGU_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -442,6 +710,12 @@ { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 }, { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_TIFINAGH, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_VAI_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, #ifdef AF_CONFIG_OPTION_CJK { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP }, { AF_BLUE_STRING_CJK_BOTTOM, 0 }, diff --git a/Source/ThirdParty/FreeType/src/autofit/afblue.cin b/Source/ThirdParty/FreeType/src/autofit/afblue.cin index 0c3cae818f..f9080c54d4 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afblue.cin +++ b/Source/ThirdParty/FreeType/src/autofit/afblue.cin @@ -4,7 +4,7 @@ /* */ /* Auto-fitter data for blue strings (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afblue.dat b/Source/ThirdParty/FreeType/src/autofit/afblue.dat index f5f04f2898..454923e9ca 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afblue.dat +++ b/Source/ThirdParty/FreeType/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright 2013-2016 by +// Copyright 2013-2017 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, @@ -74,6 +74,15 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + AF_BLUE_STRING_ADLAM_CAPITAL_TOP + "𞤌 𞤅 𞤈 𞤏 𞤔 𞤚" + AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM + "𞤂 𞤖" + AF_BLUE_STRING_ADLAM_SMALL_TOP + "𞤬 𞤮 𞤻 𞤼 𞤾" + AF_BLUE_STRING_ADLAM_SMALL_BOTTOM + "𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀" + AF_BLUE_STRING_ARABIC_TOP "ا إ ل ك ط ظ" AF_BLUE_STRING_ARABIC_BOTTOM @@ -99,6 +108,16 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER "բ ը ի լ ղ պ փ ց" + AF_BLUE_STRING_AVESTAN_TOP + "𐬀 𐬁 𐬐 𐬛" + AF_BLUE_STRING_AVESTAN_BOTTOM + "𐬀 𐬁" + + AF_BLUE_STRING_BAMUM_TOP + "ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ ꛫ ꛯ" + AF_BLUE_STRING_BAMUM_BOTTOM + "ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲" + AF_BLUE_STRING_BENGALI_BASE "অ ড ত ন ব ভ ল ক" AF_BLUE_STRING_BENGALI_TOP @@ -106,6 +125,40 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_BENGALI_HEAD "ও এ ড ত ন ব ল ক" + AF_BLUE_STRING_BUHID_TOP + "ᝐ ᝈ" + AF_BLUE_STRING_BUHID_LARGE + "ᝅ ᝊ ᝎ" + AF_BLUE_STRING_BUHID_SMALL + "ᝂ ᝃ ᝉ ᝌ" + AF_BLUE_STRING_BUHID_BOTTOM + "ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ" + + AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP + "ᗜ ᖴ ᐁ ᒣ ᑫ ᑎ ᔑ ᗰ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM + "ᗶ ᖵ ᒧ ᐃ ᑌ ᒍ ᔑ ᗢ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP + "ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM + "ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP + "ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM + "ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ" + + AF_BLUE_STRING_CARIAN_TOP + "𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿" + AF_BLUE_STRING_CARIAN_BOTTOM + "𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉" + + AF_BLUE_STRING_CHAKMA_TOP + "𑄃 𑄅 𑄉 𑄙 𑄗" + AF_BLUE_STRING_CHAKMA_BOTTOM + "𑄅 𑄛 𑄝 𑄗 𑄓" + AF_BLUE_STRING_CHAKMA_DESCENDER + "𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢" + AF_BLUE_STRING_CHEROKEE_CAPITAL "Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ" AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER @@ -115,6 +168,22 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER "ᏸ ꮐ ꭹ ꭻ" + AF_BLUE_STRING_COPTIC_CAPITAL_TOP + "Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ Ⲑ Ⲥ Ⳋ" + AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM + "Ⳑ Ⳙ Ⳟ Ⲏ Ⲟ Ⲑ Ⳝ Ⲱ" + AF_BLUE_STRING_COPTIC_SMALL_TOP + "ⲍ ⲏ ⲡ ⳟ ⲟ ⲑ ⲥ ⳋ" + AF_BLUE_STRING_COPTIC_SMALL_BOTTOM + "ⳑ ⳙ ⳟ ⲏ ⲟ ⲑ ⳝ Ⳓ" + + AF_BLUE_STRING_CYPRIOT_TOP + "𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦" + AF_BLUE_STRING_CYPRIOT_BOTTOM + "𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐" + AF_BLUE_STRING_CYPRIOT_SMALL + "𐠈 𐠏 𐠖" + AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP "Б В Е П З О С Э" AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM @@ -124,6 +193,15 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER "р у ф" + AF_BLUE_STRING_DESERET_CAPITAL_TOP + "𐐂 𐐄 𐐋 𐐗 𐐑" + AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM + "𐐀 𐐂 𐐄 𐐗 𐐛" + AF_BLUE_STRING_DESERET_SMALL_TOP + "𐐪 𐐬 𐐳 𐐿 𐐹" + AF_BLUE_STRING_DESERET_SMALL_BOTTOM + "𐐨 𐐪 𐐬 𐐿 𐑃" + AF_BLUE_STRING_DEVANAGARI_BASE "क म अ आ थ ध भ श" AF_BLUE_STRING_DEVANAGARI_TOP @@ -164,6 +242,20 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER "ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ" + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP + "Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ" + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM + "Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ" + AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP + "ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ" + AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM + "ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ" + + AF_BLUE_STRING_GOTHIC_TOP + "𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾" + AF_BLUE_STRING_GOTHIC_BOTTOM + "𐌶 𐌴 𐍃 𐍈" + AF_BLUE_STRING_GREEK_CAPITAL_TOP "Γ Β Ε Ζ Θ Ο Ω" AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM @@ -209,6 +301,17 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_KANNADA_BOTTOM "ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭" + AF_BLUE_STRING_KAYAH_LI_TOP + "꤅ ꤏ ꤁ ꤋ ꤀ ꤍ" + AF_BLUE_STRING_KAYAH_LI_BOTTOM + "꤈ ꤘ ꤀ ꤍ ꤢ" + AF_BLUE_STRING_KAYAH_LI_ASCENDER + "ꤖ ꤡ" + AF_BLUE_STRING_KAYAH_LI_DESCENDER + "ꤑ ꤜ ꤞ" + AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER + "ꤑ꤬ ꤜ꤭ ꤔ꤬" + AF_BLUE_STRING_KHMER_TOP "ខ ទ ន ឧ ឩ ា" AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP @@ -242,8 +345,10 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: "H E Z L O C U S" AF_BLUE_STRING_LATIN_SMALL_F_TOP "f i j k d b h" - AF_BLUE_STRING_LATIN_SMALL - "x z r o e s c" + AF_BLUE_STRING_LATIN_SMALL_TOP + "u v x z o e s c" + AF_BLUE_STRING_LATIN_SMALL_BOTTOM + "n r x z o e s c" AF_BLUE_STRING_LATIN_SMALL_DESCENDER "p q g j y" @@ -272,6 +377,11 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER "ᵖ ʸ ᵍ" + AF_BLUE_STRING_LISU_TOP + "ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ" + AF_BLUE_STRING_LISU_BOTTOM + "ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ" + AF_BLUE_STRING_MALAYALAM_TOP "ഒ ട ഠ റ ച പ ച്ച പ്പ" AF_BLUE_STRING_MALAYALAM_BOTTOM @@ -286,6 +396,59 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_MYANMAR_DESCENDER "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉" + AF_BLUE_STRING_NKO_TOP + "ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ" + AF_BLUE_STRING_NKO_BOTTOM + "߀ ߘ ߡ ߠ ߥ" + AF_BLUE_STRING_NKO_SMALL_TOP + "ߏ ߛ ߋ" + AF_BLUE_STRING_NKO_SMALL_BOTTOM + "ߎ ߏ ߛ ߋ" + + AF_BLUE_STRING_OL_CHIKI + "ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ" + + AF_BLUE_STRING_OLD_TURKIC_TOP + "𐰗 𐰘 𐰧" + AF_BLUE_STRING_OLD_TURKIC_BOTTOM + "𐰉 𐰗 𐰦 𐰧" + + AF_BLUE_STRING_OSAGE_CAPITAL_TOP + "𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆" + AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM + "𐒰 𐓍 𐓂 𐒿 𐓎 𐒹" + AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER + "𐒼 𐒽 𐒾" + AF_BLUE_STRING_OSAGE_SMALL_TOP + "𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮" + AF_BLUE_STRING_OSAGE_SMALL_BOTTOM + "𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶" + AF_BLUE_STRING_OSAGE_SMALL_ASCENDER + "𐓤 𐓦 𐓸 𐓹 𐓛" + AF_BLUE_STRING_OSAGE_SMALL_DESCENDER + "𐓤 𐓥 𐓦" + + AF_BLUE_STRING_OSMANYA_TOP + "𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣" + AF_BLUE_STRING_OSMANYA_BOTTOM + "𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩" + + AF_BLUE_STRING_SAURASHTRA_TOP + "ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ" + AF_BLUE_STRING_SAURASHTRA_BOTTOM + "ꢂ ꢨ ꢺ ꢤ ꢎ" + + AF_BLUE_STRING_SHAVIAN_TOP + "𐑕 𐑙" + AF_BLUE_STRING_SHAVIAN_BOTTOM + "𐑔 𐑖 𐑗 𐑹 𐑻" + AF_BLUE_STRING_SHAVIAN_DESCENDER + "𐑟 𐑣" + AF_BLUE_STRING_SHAVIAN_SMALL_TOP + "𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼" + AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM + "𐑴 𐑻 𐑹" + AF_BLUE_STRING_SINHALA_TOP "ඉ ක ඝ ඳ ප ය ල ෆ" AF_BLUE_STRING_SINHALA_BOTTOM @@ -293,6 +456,18 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_SINHALA_DESCENDER "ද ඳ උ ල තූ තු බු දු" + AF_BLUE_STRING_SUNDANESE_TOP + "ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ" + AF_BLUE_STRING_SUNDANESE_BOTTOM + "ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ" + AF_BLUE_STRING_SUNDANESE_DESCENDER + "ᮼ ᳄" + + AF_BLUE_STRING_TAI_VIET_TOP + "ꪆ ꪔ ꪒ ꪖ ꪫ" + AF_BLUE_STRING_TAI_VIET_BOTTOM + "ꪉ ꪫ ꪮ" + AF_BLUE_STRING_TAMIL_TOP "உ ஒ ஓ ற ஈ க ங ச" AF_BLUE_STRING_TAMIL_BOTTOM @@ -318,6 +493,14 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_THAI_DIGIT_TOP "๐ ๑ ๓" + AF_BLUE_STRING_TIFINAGH + "ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ" + + AF_BLUE_STRING_VAI_TOP + "ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ" + AF_BLUE_STRING_VAI_BOTTOM + "ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ" + #ifdef AF_CONFIG_OPTION_CJK @@ -483,6 +666,14 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: + AF_BLUE_STRINGSET_ADLM + { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_ARAB { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_ARABIC_BOTTOM, 0 } @@ -499,6 +690,16 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_AVST + { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_AVESTAN_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_BAMU + { AF_BLUE_STRING_BAMUM_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_BAMUM_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_BENG { AF_BLUE_STRING_BENGALI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP } @@ -508,6 +709,35 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_BENGALI_BASE, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_BUHD + { AF_BLUE_STRING_BUHID_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_BUHID_LARGE, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_BUHID_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_BUHID_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CAKM + { AF_BLUE_STRING_CHAKMA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CHAKMA_BOTTOM, 0 } + { AF_BLUE_STRING_CHAKMA_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CANS + { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CARI + { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CARIAN_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_CHER { AF_BLUE_STRING_CHEROKEE_CAPITAL, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_CHEROKEE_CAPITAL, 0 } @@ -518,6 +748,21 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_COPT + { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CPRT + { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 } + { AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CYPRIOT_SMALL, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_CYRL { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 } @@ -537,6 +782,14 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_DSRT + { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_ETHI { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 } @@ -561,6 +814,19 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_GLAG + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_GOTH + { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GOTHIC_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_GREK { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 } @@ -597,6 +863,15 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_HEBREW_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_KALI + { AF_BLUE_STRING_KAYAH_LI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_KAYAH_LI_BOTTOM, 0 } + { AF_BLUE_STRING_KAYAH_LI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 } + { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_KNDA { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_KANNADA_BOTTOM, 0 } @@ -630,9 +905,9 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 } { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | + { AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_LATIN_SMALL, 0 } + { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 } { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } @@ -656,6 +931,11 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_LISU + { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LISU_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_MLYM { AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 } @@ -669,20 +949,79 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_NKOO + { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_NKO_BOTTOM, 0 } + { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_NONE { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_OLCK + { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OL_CHIKI, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_ORKH + { AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_OSGE + { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 } + { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_OSMA + { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSMANYA_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_SAUR + { AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_SHAW + { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 } + { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 } + { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_SINH { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_SINHALA_BOTTOM, 0 } { AF_BLUE_STRING_SINHALA_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_SUND + { AF_BLUE_STRING_SUNDANESE_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SUNDANESE_BOTTOM, 0 } + { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TAML { AF_BLUE_STRING_TAMIL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_TAMIL_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TAVT + { AF_BLUE_STRING_TAI_VIET_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TELU { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_TELUGU_BOTTOM, 0 } @@ -699,6 +1038,15 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TFNG + { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_TIFINAGH, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_VAII + { AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_VAI_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } #ifdef AF_CONFIG_OPTION_CJK diff --git a/Source/ThirdParty/FreeType/src/autofit/afblue.h b/Source/ThirdParty/FreeType/src/autofit/afblue.h index 75c3ab5083..e227dbf50b 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afblue.h +++ b/Source/ThirdParty/FreeType/src/autofit/afblue.h @@ -7,7 +7,7 @@ /* */ /* Auto-fitter data for blue strings (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -77,110 +77,189 @@ FT_BEGIN_HEADER typedef enum AF_Blue_String_ { - AF_BLUE_STRING_ARABIC_TOP = 0, - AF_BLUE_STRING_ARABIC_BOTTOM = 18, - AF_BLUE_STRING_ARABIC_JOIN = 33, - AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 36, - AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 60, - AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 84, - AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 105, - AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 129, - AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 153, - AF_BLUE_STRING_BENGALI_BASE = 177, - AF_BLUE_STRING_BENGALI_TOP = 209, - AF_BLUE_STRING_BENGALI_HEAD = 237, - AF_BLUE_STRING_CHEROKEE_CAPITAL = 269, - AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 301, - AF_BLUE_STRING_CHEROKEE_SMALL = 333, - AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 365, - AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 381, - AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 405, - AF_BLUE_STRING_CYRILLIC_SMALL = 429, - AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 453, - AF_BLUE_STRING_DEVANAGARI_BASE = 462, - AF_BLUE_STRING_DEVANAGARI_TOP = 494, - AF_BLUE_STRING_DEVANAGARI_HEAD = 526, - AF_BLUE_STRING_DEVANAGARI_BOTTOM = 558, - AF_BLUE_STRING_ETHIOPIC_TOP = 566, - AF_BLUE_STRING_ETHIOPIC_BOTTOM = 598, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 630, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 662, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 694, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 726, - AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 758, - AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 790, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 822, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 854, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 886, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 918, - AF_BLUE_STRING_GREEK_CAPITAL_TOP = 950, - AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 971, - AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 989, - AF_BLUE_STRING_GREEK_SMALL = 1007, - AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 1031, - AF_BLUE_STRING_GUJARATI_TOP = 1055, - AF_BLUE_STRING_GUJARATI_BOTTOM = 1087, - AF_BLUE_STRING_GUJARATI_ASCENDER = 1119, - AF_BLUE_STRING_GUJARATI_DESCENDER = 1169, - AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 1202, - AF_BLUE_STRING_GURMUKHI_BASE = 1222, - AF_BLUE_STRING_GURMUKHI_HEAD = 1254, - AF_BLUE_STRING_GURMUKHI_TOP = 1286, - AF_BLUE_STRING_GURMUKHI_BOTTOM = 1318, - AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 1350, - AF_BLUE_STRING_HEBREW_TOP = 1370, - AF_BLUE_STRING_HEBREW_BOTTOM = 1394, - AF_BLUE_STRING_HEBREW_DESCENDER = 1412, - AF_BLUE_STRING_KANNADA_TOP = 1427, - AF_BLUE_STRING_KANNADA_BOTTOM = 1471, - AF_BLUE_STRING_KHMER_TOP = 1503, - AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 1527, - AF_BLUE_STRING_KHMER_BOTTOM = 1567, - AF_BLUE_STRING_KHMER_DESCENDER = 1599, - AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 1633, - AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 1720, - AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 1728, - AF_BLUE_STRING_LAO_TOP = 1736, - AF_BLUE_STRING_LAO_BOTTOM = 1768, - AF_BLUE_STRING_LAO_ASCENDER = 1800, - AF_BLUE_STRING_LAO_LARGE_ASCENDER = 1816, - AF_BLUE_STRING_LAO_DESCENDER = 1828, - AF_BLUE_STRING_LATIN_CAPITAL_TOP = 1852, - AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 1868, - AF_BLUE_STRING_LATIN_SMALL_F_TOP = 1884, - AF_BLUE_STRING_LATIN_SMALL = 1898, - AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 1912, - AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 1922, - AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 1942, - AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 1962, - AF_BLUE_STRING_LATIN_SUBS_SMALL = 1982, - AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 2018, - AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 2038, - AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 2069, - AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 2098, - AF_BLUE_STRING_LATIN_SUPS_SMALL = 2124, - AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 2149, - AF_BLUE_STRING_MALAYALAM_TOP = 2160, - AF_BLUE_STRING_MALAYALAM_BOTTOM = 2204, - AF_BLUE_STRING_MYANMAR_TOP = 2236, - AF_BLUE_STRING_MYANMAR_BOTTOM = 2268, - AF_BLUE_STRING_MYANMAR_ASCENDER = 2300, - AF_BLUE_STRING_MYANMAR_DESCENDER = 2328, - AF_BLUE_STRING_SINHALA_TOP = 2360, - AF_BLUE_STRING_SINHALA_BOTTOM = 2392, - AF_BLUE_STRING_SINHALA_DESCENDER = 2424, - AF_BLUE_STRING_TAMIL_TOP = 2468, - AF_BLUE_STRING_TAMIL_BOTTOM = 2500, - AF_BLUE_STRING_TELUGU_TOP = 2532, - AF_BLUE_STRING_TELUGU_BOTTOM = 2560, - AF_BLUE_STRING_THAI_TOP = 2588, - AF_BLUE_STRING_THAI_BOTTOM = 2612, - AF_BLUE_STRING_THAI_ASCENDER = 2640, - AF_BLUE_STRING_THAI_LARGE_ASCENDER = 2652, - AF_BLUE_STRING_THAI_DESCENDER = 2664, - AF_BLUE_STRING_THAI_LARGE_DESCENDER = 2680, - AF_BLUE_STRING_THAI_DIGIT_TOP = 2688, - af_blue_1_1 = 2699, + AF_BLUE_STRING_ADLAM_CAPITAL_TOP = 0, + AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM = 30, + AF_BLUE_STRING_ADLAM_SMALL_TOP = 40, + AF_BLUE_STRING_ADLAM_SMALL_BOTTOM = 65, + AF_BLUE_STRING_ARABIC_TOP = 105, + AF_BLUE_STRING_ARABIC_BOTTOM = 123, + AF_BLUE_STRING_ARABIC_JOIN = 138, + AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 141, + AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 165, + AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 189, + AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 210, + AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 234, + AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 258, + AF_BLUE_STRING_AVESTAN_TOP = 282, + AF_BLUE_STRING_AVESTAN_BOTTOM = 302, + AF_BLUE_STRING_BAMUM_TOP = 312, + AF_BLUE_STRING_BAMUM_BOTTOM = 344, + AF_BLUE_STRING_BENGALI_BASE = 376, + AF_BLUE_STRING_BENGALI_TOP = 408, + AF_BLUE_STRING_BENGALI_HEAD = 436, + AF_BLUE_STRING_BUHID_TOP = 468, + AF_BLUE_STRING_BUHID_LARGE = 476, + AF_BLUE_STRING_BUHID_SMALL = 488, + AF_BLUE_STRING_BUHID_BOTTOM = 504, + AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP = 532, + AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM = 564, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP = 596, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM = 628, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP = 660, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM = 688, + AF_BLUE_STRING_CARIAN_TOP = 720, + AF_BLUE_STRING_CARIAN_BOTTOM = 760, + AF_BLUE_STRING_CHAKMA_TOP = 795, + AF_BLUE_STRING_CHAKMA_BOTTOM = 820, + AF_BLUE_STRING_CHAKMA_DESCENDER = 845, + AF_BLUE_STRING_CHEROKEE_CAPITAL = 910, + AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 942, + AF_BLUE_STRING_CHEROKEE_SMALL = 974, + AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 1006, + AF_BLUE_STRING_COPTIC_CAPITAL_TOP = 1022, + AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM = 1054, + AF_BLUE_STRING_COPTIC_SMALL_TOP = 1086, + AF_BLUE_STRING_COPTIC_SMALL_BOTTOM = 1118, + AF_BLUE_STRING_CYPRIOT_TOP = 1150, + AF_BLUE_STRING_CYPRIOT_BOTTOM = 1190, + AF_BLUE_STRING_CYPRIOT_SMALL = 1225, + AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 1240, + AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 1264, + AF_BLUE_STRING_CYRILLIC_SMALL = 1288, + AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 1312, + AF_BLUE_STRING_DESERET_CAPITAL_TOP = 1321, + AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM = 1346, + AF_BLUE_STRING_DESERET_SMALL_TOP = 1371, + AF_BLUE_STRING_DESERET_SMALL_BOTTOM = 1396, + AF_BLUE_STRING_DEVANAGARI_BASE = 1421, + AF_BLUE_STRING_DEVANAGARI_TOP = 1453, + AF_BLUE_STRING_DEVANAGARI_HEAD = 1485, + AF_BLUE_STRING_DEVANAGARI_BOTTOM = 1517, + AF_BLUE_STRING_ETHIOPIC_TOP = 1525, + AF_BLUE_STRING_ETHIOPIC_BOTTOM = 1557, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 1589, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 1621, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 1653, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 1685, + AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 1717, + AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 1749, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 1781, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 1813, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 1845, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 1877, + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP = 1909, + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM = 1941, + AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP = 1973, + AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM = 2005, + AF_BLUE_STRING_GOTHIC_TOP = 2037, + AF_BLUE_STRING_GOTHIC_BOTTOM = 2077, + AF_BLUE_STRING_GREEK_CAPITAL_TOP = 2097, + AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 2118, + AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 2136, + AF_BLUE_STRING_GREEK_SMALL = 2154, + AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 2178, + AF_BLUE_STRING_GUJARATI_TOP = 2202, + AF_BLUE_STRING_GUJARATI_BOTTOM = 2234, + AF_BLUE_STRING_GUJARATI_ASCENDER = 2266, + AF_BLUE_STRING_GUJARATI_DESCENDER = 2316, + AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 2349, + AF_BLUE_STRING_GURMUKHI_BASE = 2369, + AF_BLUE_STRING_GURMUKHI_HEAD = 2401, + AF_BLUE_STRING_GURMUKHI_TOP = 2433, + AF_BLUE_STRING_GURMUKHI_BOTTOM = 2465, + AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 2497, + AF_BLUE_STRING_HEBREW_TOP = 2517, + AF_BLUE_STRING_HEBREW_BOTTOM = 2541, + AF_BLUE_STRING_HEBREW_DESCENDER = 2559, + AF_BLUE_STRING_KANNADA_TOP = 2574, + AF_BLUE_STRING_KANNADA_BOTTOM = 2618, + AF_BLUE_STRING_KAYAH_LI_TOP = 2650, + AF_BLUE_STRING_KAYAH_LI_BOTTOM = 2674, + AF_BLUE_STRING_KAYAH_LI_ASCENDER = 2694, + AF_BLUE_STRING_KAYAH_LI_DESCENDER = 2702, + AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER = 2714, + AF_BLUE_STRING_KHMER_TOP = 2735, + AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 2759, + AF_BLUE_STRING_KHMER_BOTTOM = 2799, + AF_BLUE_STRING_KHMER_DESCENDER = 2831, + AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 2865, + AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 2952, + AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 2960, + AF_BLUE_STRING_LAO_TOP = 2968, + AF_BLUE_STRING_LAO_BOTTOM = 3000, + AF_BLUE_STRING_LAO_ASCENDER = 3032, + AF_BLUE_STRING_LAO_LARGE_ASCENDER = 3048, + AF_BLUE_STRING_LAO_DESCENDER = 3060, + AF_BLUE_STRING_LATIN_CAPITAL_TOP = 3084, + AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 3100, + AF_BLUE_STRING_LATIN_SMALL_F_TOP = 3116, + AF_BLUE_STRING_LATIN_SMALL_TOP = 3130, + AF_BLUE_STRING_LATIN_SMALL_BOTTOM = 3146, + AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 3162, + AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 3172, + AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 3192, + AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 3212, + AF_BLUE_STRING_LATIN_SUBS_SMALL = 3232, + AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 3268, + AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 3288, + AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 3319, + AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 3348, + AF_BLUE_STRING_LATIN_SUPS_SMALL = 3374, + AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 3399, + AF_BLUE_STRING_LISU_TOP = 3410, + AF_BLUE_STRING_LISU_BOTTOM = 3442, + AF_BLUE_STRING_MALAYALAM_TOP = 3474, + AF_BLUE_STRING_MALAYALAM_BOTTOM = 3518, + AF_BLUE_STRING_MYANMAR_TOP = 3550, + AF_BLUE_STRING_MYANMAR_BOTTOM = 3582, + AF_BLUE_STRING_MYANMAR_ASCENDER = 3614, + AF_BLUE_STRING_MYANMAR_DESCENDER = 3642, + AF_BLUE_STRING_NKO_TOP = 3674, + AF_BLUE_STRING_NKO_BOTTOM = 3698, + AF_BLUE_STRING_NKO_SMALL_TOP = 3713, + AF_BLUE_STRING_NKO_SMALL_BOTTOM = 3722, + AF_BLUE_STRING_OL_CHIKI = 3734, + AF_BLUE_STRING_OLD_TURKIC_TOP = 3758, + AF_BLUE_STRING_OLD_TURKIC_BOTTOM = 3773, + AF_BLUE_STRING_OSAGE_CAPITAL_TOP = 3793, + AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM = 3833, + AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER = 3863, + AF_BLUE_STRING_OSAGE_SMALL_TOP = 3878, + AF_BLUE_STRING_OSAGE_SMALL_BOTTOM = 3918, + AF_BLUE_STRING_OSAGE_SMALL_ASCENDER = 3958, + AF_BLUE_STRING_OSAGE_SMALL_DESCENDER = 3983, + AF_BLUE_STRING_OSMANYA_TOP = 3998, + AF_BLUE_STRING_OSMANYA_BOTTOM = 4038, + AF_BLUE_STRING_SAURASHTRA_TOP = 4078, + AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4110, + AF_BLUE_STRING_SHAVIAN_TOP = 4130, + AF_BLUE_STRING_SHAVIAN_BOTTOM = 4140, + AF_BLUE_STRING_SHAVIAN_DESCENDER = 4165, + AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4175, + AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4210, + AF_BLUE_STRING_SINHALA_TOP = 4225, + AF_BLUE_STRING_SINHALA_BOTTOM = 4257, + AF_BLUE_STRING_SINHALA_DESCENDER = 4289, + AF_BLUE_STRING_SUNDANESE_TOP = 4333, + AF_BLUE_STRING_SUNDANESE_BOTTOM = 4357, + AF_BLUE_STRING_SUNDANESE_DESCENDER = 4389, + AF_BLUE_STRING_TAI_VIET_TOP = 4397, + AF_BLUE_STRING_TAI_VIET_BOTTOM = 4417, + AF_BLUE_STRING_TAMIL_TOP = 4429, + AF_BLUE_STRING_TAMIL_BOTTOM = 4461, + AF_BLUE_STRING_TELUGU_TOP = 4493, + AF_BLUE_STRING_TELUGU_BOTTOM = 4521, + AF_BLUE_STRING_THAI_TOP = 4549, + AF_BLUE_STRING_THAI_BOTTOM = 4573, + AF_BLUE_STRING_THAI_ASCENDER = 4601, + AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4613, + AF_BLUE_STRING_THAI_DESCENDER = 4625, + AF_BLUE_STRING_THAI_LARGE_DESCENDER = 4641, + AF_BLUE_STRING_THAI_DIGIT_TOP = 4649, + AF_BLUE_STRING_TIFINAGH = 4661, + AF_BLUE_STRING_VAI_TOP = 4693, + AF_BLUE_STRING_VAI_BOTTOM = 4725, + af_blue_1_1 = 4756, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1, AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203, @@ -239,34 +318,59 @@ FT_BEGIN_HEADER typedef enum AF_Blue_Stringset_ { - AF_BLUE_STRINGSET_ARAB = 0, - AF_BLUE_STRINGSET_ARMN = 4, - AF_BLUE_STRINGSET_BENG = 11, - AF_BLUE_STRINGSET_CHER = 16, - AF_BLUE_STRINGSET_CYRL = 23, - AF_BLUE_STRINGSET_DEVA = 29, - AF_BLUE_STRINGSET_ETHI = 35, - AF_BLUE_STRINGSET_GEOR = 38, - AF_BLUE_STRINGSET_GEOK = 43, - AF_BLUE_STRINGSET_GREK = 50, - AF_BLUE_STRINGSET_GUJR = 57, - AF_BLUE_STRINGSET_GURU = 63, - AF_BLUE_STRINGSET_HEBR = 69, - AF_BLUE_STRINGSET_KNDA = 73, - AF_BLUE_STRINGSET_KHMR = 76, - AF_BLUE_STRINGSET_KHMS = 82, - AF_BLUE_STRINGSET_LAO = 85, - AF_BLUE_STRINGSET_LATN = 91, - AF_BLUE_STRINGSET_LATB = 98, - AF_BLUE_STRINGSET_LATP = 105, - AF_BLUE_STRINGSET_MLYM = 112, - AF_BLUE_STRINGSET_MYMR = 115, - AF_BLUE_STRINGSET_NONE = 120, - AF_BLUE_STRINGSET_SINH = 121, - AF_BLUE_STRINGSET_TAML = 125, - AF_BLUE_STRINGSET_TELU = 128, - AF_BLUE_STRINGSET_THAI = 131, - af_blue_2_1 = 139, + AF_BLUE_STRINGSET_ADLM = 0, + AF_BLUE_STRINGSET_ARAB = 5, + AF_BLUE_STRINGSET_ARMN = 9, + AF_BLUE_STRINGSET_AVST = 16, + AF_BLUE_STRINGSET_BAMU = 19, + AF_BLUE_STRINGSET_BENG = 22, + AF_BLUE_STRINGSET_BUHD = 27, + AF_BLUE_STRINGSET_CAKM = 32, + AF_BLUE_STRINGSET_CANS = 36, + AF_BLUE_STRINGSET_CARI = 43, + AF_BLUE_STRINGSET_CHER = 46, + AF_BLUE_STRINGSET_COPT = 53, + AF_BLUE_STRINGSET_CPRT = 58, + AF_BLUE_STRINGSET_CYRL = 63, + AF_BLUE_STRINGSET_DEVA = 69, + AF_BLUE_STRINGSET_DSRT = 75, + AF_BLUE_STRINGSET_ETHI = 80, + AF_BLUE_STRINGSET_GEOR = 83, + AF_BLUE_STRINGSET_GEOK = 88, + AF_BLUE_STRINGSET_GLAG = 95, + AF_BLUE_STRINGSET_GOTH = 100, + AF_BLUE_STRINGSET_GREK = 103, + AF_BLUE_STRINGSET_GUJR = 110, + AF_BLUE_STRINGSET_GURU = 116, + AF_BLUE_STRINGSET_HEBR = 122, + AF_BLUE_STRINGSET_KALI = 126, + AF_BLUE_STRINGSET_KNDA = 132, + AF_BLUE_STRINGSET_KHMR = 135, + AF_BLUE_STRINGSET_KHMS = 141, + AF_BLUE_STRINGSET_LAO = 144, + AF_BLUE_STRINGSET_LATN = 150, + AF_BLUE_STRINGSET_LATB = 157, + AF_BLUE_STRINGSET_LATP = 164, + AF_BLUE_STRINGSET_LISU = 171, + AF_BLUE_STRINGSET_MLYM = 174, + AF_BLUE_STRINGSET_MYMR = 177, + AF_BLUE_STRINGSET_NKOO = 182, + AF_BLUE_STRINGSET_NONE = 187, + AF_BLUE_STRINGSET_OLCK = 188, + AF_BLUE_STRINGSET_ORKH = 191, + AF_BLUE_STRINGSET_OSGE = 194, + AF_BLUE_STRINGSET_OSMA = 202, + AF_BLUE_STRINGSET_SAUR = 205, + AF_BLUE_STRINGSET_SHAW = 208, + AF_BLUE_STRINGSET_SINH = 214, + AF_BLUE_STRINGSET_SUND = 218, + AF_BLUE_STRINGSET_TAML = 222, + AF_BLUE_STRINGSET_TAVT = 225, + AF_BLUE_STRINGSET_TELU = 228, + AF_BLUE_STRINGSET_THAI = 231, + AF_BLUE_STRINGSET_TFNG = 239, + AF_BLUE_STRINGSET_VAII = 242, + af_blue_2_1 = 245, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0, af_blue_2_1_1 = af_blue_2_1 + 2, diff --git a/Source/ThirdParty/FreeType/src/autofit/afblue.hin b/Source/ThirdParty/FreeType/src/autofit/afblue.hin index dd44e77254..268bcbc531 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afblue.hin +++ b/Source/ThirdParty/FreeType/src/autofit/afblue.hin @@ -4,7 +4,7 @@ /* */ /* Auto-fitter data for blue strings (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afcjk.c b/Source/ThirdParty/FreeType/src/autofit/afcjk.c index 4126633151..61e29cdeda 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afcjk.c +++ b/Source/ThirdParty/FreeType/src/autofit/afcjk.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK writing system (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,13 +29,13 @@ #include "afglobal.h" #include "afpic.h" #include "aflatin.h" +#include "afcjk.h" #ifdef AF_CONFIG_OPTION_CJK #undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT -#include "afcjk.h" #include "aferrors.h" @@ -563,7 +563,7 @@ FT_Face face ) { FT_Bool started = 0, same_width = 1; - FT_Fixed advance, old_advance = 0; + FT_Fixed advance = 0, old_advance = 0; void* shaper_buf; @@ -1398,9 +1398,9 @@ other_flags |= AF_LATIN_HINTS_VERT_SNAP; /* - * We adjust stems to full pixels only if we don't use the `light' mode. + * We adjust stems to full pixels unless in `light' or `lcd' mode. */ - if ( mode != FT_RENDER_MODE_LIGHT ) + if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) other_flags |= AF_LATIN_HINTS_STEM_ADJUST; if ( mode == FT_RENDER_MODE_MONO ) diff --git a/Source/ThirdParty/FreeType/src/autofit/afcjk.h b/Source/ThirdParty/FreeType/src/autofit/afcjk.h index 40d1184386..84f892f909 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afcjk.h +++ b/Source/ThirdParty/FreeType/src/autofit/afcjk.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK writing system (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afcover.h b/Source/ThirdParty/FreeType/src/autofit/afcover.h index 1c39a707ef..1b18c666ab 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afcover.h +++ b/Source/ThirdParty/FreeType/src/autofit/afcover.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter coverages (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afdummy.c b/Source/ThirdParty/FreeType/src/autofit/afdummy.c index ff47dcb0c0..61c32db5bf 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afdummy.c +++ b/Source/ThirdParty/FreeType/src/autofit/afdummy.c @@ -5,7 +5,7 @@ /* Auto-fitter dummy routines to be used if no hinting should be */ /* performed (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afdummy.h b/Source/ThirdParty/FreeType/src/autofit/afdummy.h index 7e58d1a9a5..ebaa7d76ea 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afdummy.h +++ b/Source/ThirdParty/FreeType/src/autofit/afdummy.h @@ -5,7 +5,7 @@ /* Auto-fitter dummy routines to be used if no hinting should be */ /* performed (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/aferrors.h b/Source/ThirdParty/FreeType/src/autofit/aferrors.h index 53c01f64dd..dde182f3c8 100644 --- a/Source/ThirdParty/FreeType/src/autofit/aferrors.h +++ b/Source/ThirdParty/FreeType/src/autofit/aferrors.h @@ -4,7 +4,7 @@ /* */ /* Autofitter error codes (specification only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afglobal.c b/Source/ThirdParty/FreeType/src/autofit/afglobal.c index 11ed0dff94..85bef001f7 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afglobal.c +++ b/Source/ThirdParty/FreeType/src/autofit/afglobal.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter routines to compute global hinting values (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -411,10 +411,7 @@ #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ hb_font_destroy( globals->hb_font ); - globals->hb_font = NULL; - hb_buffer_destroy( globals->hb_buf ); - globals->hb_buf = NULL; #endif /* no need to free `globals->glyph_styles'; */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afglobal.h b/Source/ThirdParty/FreeType/src/autofit/afglobal.h index ce6b9e8f26..de6142ea26 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afglobal.h +++ b/Source/ThirdParty/FreeType/src/autofit/afglobal.h @@ -5,7 +5,7 @@ /* Auto-fitter routines to compute global hinting values */ /* (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afhints.c b/Source/ThirdParty/FreeType/src/autofit/afhints.c index 8ad3e1c978..f1ff0baef8 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afhints.c +++ b/Source/ThirdParty/FreeType/src/autofit/afhints.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afhints.h b/Source/ThirdParty/FreeType/src/autofit/afhints.h index 4fdf732d42..16638b1030 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afhints.h +++ b/Source/ThirdParty/FreeType/src/autofit/afhints.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afindic.c b/Source/ThirdParty/FreeType/src/autofit/afindic.c index cfaf7196d6..23be46ed51 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afindic.c +++ b/Source/ThirdParty/FreeType/src/autofit/afindic.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for Indic writing system (body). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,13 +18,13 @@ #include "aftypes.h" #include "aflatin.h" +#include "afcjk.h" #ifdef AF_CONFIG_OPTION_INDIC #include "afindic.h" #include "aferrors.h" -#include "afcjk.h" #ifdef AF_CONFIG_OPTION_USE_WARPER diff --git a/Source/ThirdParty/FreeType/src/autofit/afindic.h b/Source/ThirdParty/FreeType/src/autofit/afindic.h index 0772e07a29..ec9e263161 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afindic.h +++ b/Source/ThirdParty/FreeType/src/autofit/afindic.h @@ -5,7 +5,7 @@ /* Auto-fitter hinting routines for Indic writing system */ /* (specification). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/aflatin.c b/Source/ThirdParty/FreeType/src/autofit/aflatin.c index f4d29e7b88..11fa523c83 100644 --- a/Source/ThirdParty/FreeType/src/autofit/aflatin.c +++ b/Source/ThirdParty/FreeType/src/autofit/aflatin.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin writing system (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -265,6 +265,45 @@ } + static void + af_latin_sort_blue( FT_UInt count, + AF_LatinBlue* table ) + { + FT_UInt i, j; + AF_LatinBlue swap; + + + /* we sort from bottom to top */ + for ( i = 1; i < count; i++ ) + { + for ( j = i; j > 0; j-- ) + { + FT_Pos a, b; + + + if ( table[j - 1]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + a = table[j - 1]->ref.org; + else + a = table[j - 1]->shoot.org; + + if ( table[j]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + b = table[j]->ref.org; + else + b = table[j]->shoot.org; + + if ( b >= a ) + break; + + swap = table[j]; + table[j] = table[j - 1]; + table[j - 1] = swap; + } + } + } + + /* Find all blue zones. Flat segments give the reference points, */ /* round segments the overshoot positions. */ @@ -928,6 +967,60 @@ af_shaper_buf_destroy( face, shaper_buf ); + /* we finally check whether blue zones are ordered; */ + /* `ref' and `shoot' values of two blue zones must not overlap */ + if ( axis->blue_count ) + { + FT_UInt i; + AF_LatinBlue blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2]; + + + for ( i = 0; i < axis->blue_count; i++ ) + blue_sorted[i] = &axis->blues[i]; + + /* sort bottoms of blue zones... */ + af_latin_sort_blue( axis->blue_count, blue_sorted ); + + /* ...and adjust top values if necessary */ + for ( i = 0; i < axis->blue_count - 1; i++ ) + { + FT_Pos* a; + FT_Pos* b; + +#ifdef FT_DEBUG_LEVEL_TRACE + FT_Bool a_is_top = 0; +#endif + + + if ( blue_sorted[i]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + { + a = &blue_sorted[i]->shoot.org; +#ifdef FT_DEBUG_LEVEL_TRACE + a_is_top = 1; +#endif + } + else + a = &blue_sorted[i]->ref.org; + + if ( blue_sorted[i + 1]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + b = &blue_sorted[i + 1]->shoot.org; + else + b = &blue_sorted[i + 1]->ref.org; + + if ( *a > *b ) + { + *a = *b; + FT_TRACE5(( "blue zone overlap:" + " adjusting %s %d to %ld\n", + a_is_top ? "overshoot" : "reference", + blue_sorted[i] - axis->blues, + *a )); + } + } + } + FT_TRACE5(( "\n" )); return; @@ -941,7 +1034,7 @@ FT_Face face ) { FT_Bool started = 0, same_width = 1; - FT_Fixed advance, old_advance = 0; + FT_Fixed advance = 0, old_advance = 0; void* shaper_buf; @@ -1951,6 +2044,10 @@ FT_Memory memory = hints->memory; AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; +#ifdef FT_CONFIG_OPTION_PIC + AF_FaceGlobals globals = hints->metrics->globals; +#endif + AF_StyleClass style_class = hints->metrics->style_class; AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET [style_class->script]; @@ -2478,23 +2575,23 @@ other_flags |= AF_LATIN_HINTS_VERT_SNAP; /* - * We adjust stems to full pixels only if we don't use the `light' mode. + * We adjust stems to full pixels unless in `light' or `lcd' mode. */ - if ( mode != FT_RENDER_MODE_LIGHT ) + if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) other_flags |= AF_LATIN_HINTS_STEM_ADJUST; if ( mode == FT_RENDER_MODE_MONO ) other_flags |= AF_LATIN_HINTS_MONO; /* - * In `light' hinting mode we disable horizontal hinting completely. + * In `light' or `lcd' mode we disable horizontal hinting completely. * We also do it if the face is italic. * * However, if warping is enabled (which only works in `light' hinting * mode), advance widths get adjusted, too. */ - if ( mode == FT_RENDER_MODE_LIGHT || - ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) + if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD || + ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; #ifdef AF_CONFIG_OPTION_USE_WARPER @@ -2834,6 +2931,10 @@ AF_Edge anchor = NULL; FT_Int has_serifs = 0; +#ifdef FT_CONFIG_OPTION_PIC + AF_FaceGlobals globals = hints->metrics->globals; +#endif + AF_StyleClass style_class = hints->metrics->style_class; AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET [style_class->script]; diff --git a/Source/ThirdParty/FreeType/src/autofit/aflatin.h b/Source/ThirdParty/FreeType/src/autofit/aflatin.h index fe6bbd801a..d80e125ddc 100644 --- a/Source/ThirdParty/FreeType/src/autofit/aflatin.h +++ b/Source/ThirdParty/FreeType/src/autofit/aflatin.h @@ -5,7 +5,7 @@ /* Auto-fitter hinting routines for latin writing system */ /* (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/aflatin2.c b/Source/ThirdParty/FreeType/src/autofit/aflatin2.c index e1cc1f56df..0607278b1e 100644 --- a/Source/ThirdParty/FreeType/src/autofit/aflatin2.c +++ b/Source/ThirdParty/FreeType/src/autofit/aflatin2.c @@ -9,7 +9,7 @@ /* */ /* Auto-fitter hinting routines for latin writing system (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,6 +23,9 @@ #include FT_ADVANCES_H + +#ifdef FT_OPTION_AUTOFIT2 + #include "afglobal.h" #include "aflatin.h" #include "aflatin2.h" @@ -1555,20 +1558,20 @@ other_flags |= AF_LATIN_HINTS_VERT_SNAP; /* - * We adjust stems to full pixels only if we don't use the `light' mode. + * We adjust stems to full pixels unless in `light' or `lcd' mode. */ - if ( mode != FT_RENDER_MODE_LIGHT ) + if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) other_flags |= AF_LATIN_HINTS_STEM_ADJUST; if ( mode == FT_RENDER_MODE_MONO ) other_flags |= AF_LATIN_HINTS_MONO; /* - * In `light' hinting mode we disable horizontal hinting completely. + * In `light' or `lcd' mode we disable horizontal hinting completely. * We also do it if the face is italic. */ - if ( mode == FT_RENDER_MODE_LIGHT || - ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) + if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD || + ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; #ifdef AF_CONFIG_OPTION_USE_WARPER @@ -2419,5 +2422,12 @@ (AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply /* style_hints_apply */ ) +#else /* !FT_OPTION_AUTOFIT2 */ + + /* ANSI C doesn't like empty source files */ + typedef int _af_latin2_dummy; + +#endif /* !FT_OPTION_AUTOFIT2 */ + /* END */ diff --git a/Source/ThirdParty/FreeType/src/autofit/aflatin2.h b/Source/ThirdParty/FreeType/src/autofit/aflatin2.h index f83f704289..2d0b154f58 100644 --- a/Source/ThirdParty/FreeType/src/autofit/aflatin2.h +++ b/Source/ThirdParty/FreeType/src/autofit/aflatin2.h @@ -10,7 +10,7 @@ /* Auto-fitter hinting routines for latin writing system */ /* (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afloader.c b/Source/ThirdParty/FreeType/src/autofit/afloader.c index 7f75fc349e..78c4368b61 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afloader.c +++ b/Source/ThirdParty/FreeType/src/autofit/afloader.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter glyph loading routines (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -97,11 +97,13 @@ AF_FaceGlobals globals = loader->globals; AF_WritingSystemClass writing_system_class; + FT_Size_Metrics* size_metrics = &face->size->internal->autohint_metrics; + FT_Pos stdVW = 0; FT_Pos stdHW = 0; - FT_Bool size_changed = face->size->metrics.x_ppem - != globals->stem_darkening_for_ppem; + FT_Bool size_changed = size_metrics->x_ppem != + globals->stem_darkening_for_ppem; FT_Fixed em_size = af_intToFixed( face->units_per_EM ); FT_Fixed em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size ); @@ -112,7 +114,7 @@ /* Skip stem darkening for broken fonts. */ if ( !face->units_per_EM ) { - error = FT_Err_Corrupted_Font_Header; + error = FT_ERR( Corrupted_Font_Header ); goto Exit; } @@ -130,7 +132,7 @@ &stdVW ); else { - error = FT_Err_Unimplemented_Feature; + error = FT_ERR( Unimplemented_Feature ); goto Exit; } @@ -145,11 +147,11 @@ face, stdVW ) ); darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x, - face->size->metrics.x_scale ), + size_metrics->x_scale ), em_ratio ); globals->standard_vertical_width = stdVW; - globals->stem_darkening_for_ppem = face->size->metrics.x_ppem; + globals->stem_darkening_for_ppem = size_metrics->x_ppem; globals->darken_x = af_fixedToInt( darken_x ); } @@ -164,11 +166,11 @@ face, stdHW ) ); darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y, - face->size->metrics.y_scale ), + size_metrics->y_scale ), em_ratio ); globals->standard_horizontal_width = stdHW; - globals->stem_darkening_for_ppem = face->size->metrics.x_ppem; + globals->stem_darkening_for_ppem = size_metrics->x_ppem; globals->darken_y = af_fixedToInt( darken_y ); /* @@ -217,15 +219,16 @@ { FT_Error error; - FT_Size size = face->size; - FT_GlyphSlot slot = face->glyph; - FT_Slot_Internal internal = slot->internal; - FT_GlyphLoader gloader = internal->loader; + FT_Size size = face->size; + FT_Size_Internal size_internal = size->internal; + FT_GlyphSlot slot = face->glyph; + FT_Slot_Internal slot_internal = slot->internal; + FT_GlyphLoader gloader = slot_internal->loader; - AF_GlyphHints hints = loader->hints; + AF_GlyphHints hints = loader->hints; AF_ScalerRec scaler; AF_StyleMetrics style_metrics; - FT_UInt style_options = AF_STYLE_NONE_DFLT; + FT_UInt style_options = AF_STYLE_NONE_DFLT; AF_StyleClass style_class; AF_WritingSystemClass writing_system_class; @@ -239,24 +242,65 @@ FT_ZERO( &scaler ); + if ( !size_internal->autohint_metrics.x_scale || + size_internal->autohint_mode != FT_LOAD_TARGET_MODE( load_flags ) ) + { + /* switching between hinting modes usually means different scaling */ + /* values; this later on enforces recomputation of everything */ + /* related to the current size */ + + size_internal->autohint_mode = FT_LOAD_TARGET_MODE( load_flags ); + size_internal->autohint_metrics = size->metrics; + +#ifdef AF_CONFIG_OPTION_TT_SIZE_METRICS + { + FT_Size_Metrics* size_metrics = &size_internal->autohint_metrics; + + + /* set metrics to integer values and adjust scaling accordingly; */ + /* this is the same setup as with TrueType fonts, cf. function */ + /* `tt_size_reset' in file `ttobjs.c' */ + size_metrics->ascender = FT_PIX_ROUND( + FT_MulFix( face->ascender, + size_metrics->y_scale ) ); + size_metrics->descender = FT_PIX_ROUND( + FT_MulFix( face->descender, + size_metrics->y_scale ) ); + size_metrics->height = FT_PIX_ROUND( + FT_MulFix( face->height, + size_metrics->y_scale ) ); + + size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, + face->units_per_EM ); + size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, + face->units_per_EM ); + size_metrics->max_advance = FT_PIX_ROUND( + FT_MulFix( face->max_advance_width, + size_metrics->x_scale ) ); + } +#endif /* AF_CONFIG_OPTION_TT_SIZE_METRICS */ + } + /* * TODO: This code currently doesn't support fractional advance widths, - * i.e. placing hinted glyphs at anything other than integer + * i.e., placing hinted glyphs at anything other than integer * x-positions. This is only relevant for the warper code, which * scales and shifts glyphs to optimize blackness of stems (hinting on * the x-axis by nature places things on pixel integers, hinting on the - * y-axis only, i.e. LIGHT mode, doesn't touch the x-axis). The delta + * y-axis only, i.e., LIGHT mode, doesn't touch the x-axis). The delta * values of the scaler would need to be adjusted. */ scaler.face = face; - scaler.x_scale = size->metrics.x_scale; + scaler.x_scale = size_internal->autohint_metrics.x_scale; scaler.x_delta = 0; - scaler.y_scale = size->metrics.y_scale; + scaler.y_scale = size_internal->autohint_metrics.y_scale; scaler.y_delta = 0; scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags ); scaler.flags = 0; + /* note that the fallback style can't be changed anymore */ + /* after the first call of `af_loader_load_glyph' */ error = af_loader_reset( loader, module, face ); if ( error ) goto Exit; @@ -334,18 +378,24 @@ * `standard_{vertical,horizontal}_width' change. * * Ignore errors and carry on without emboldening. + * */ - if ( !module->no_stem_darkening ) + + /* stem darkening only works well in `light' mode */ + if ( scaler.render_mode == FT_RENDER_MODE_LIGHT && + ( !face->internal->no_stem_darkening || + ( face->internal->no_stem_darkening < 0 && + !module->no_stem_darkening ) ) ) af_loader_embolden_glyph_in_slot( loader, face, style_metrics ); - loader->transformed = internal->glyph_transformed; + loader->transformed = slot_internal->glyph_transformed; if ( loader->transformed ) { FT_Matrix inverse; - loader->trans_matrix = internal->glyph_matrix; - loader->trans_delta = internal->glyph_delta; + loader->trans_matrix = slot_internal->glyph_matrix; + loader->trans_delta = slot_internal->glyph_delta; inverse = loader->trans_matrix; if ( !FT_Matrix_Invert( &inverse ) ) @@ -375,18 +425,11 @@ /* now load the slot image into the auto-outline */ /* and run the automatic hinting process */ - { -#ifdef FT_CONFIG_OPTION_PIC - AF_FaceGlobals globals = loader->globals; -#endif - - - if ( writing_system_class->style_hints_apply ) - writing_system_class->style_hints_apply( glyph_index, - hints, - &gloader->base.outline, - style_metrics ); - } + if ( writing_system_class->style_hints_apply ) + writing_system_class->style_hints_apply( glyph_index, + hints, + &gloader->base.outline, + style_metrics ); /* we now need to adjust the metrics according to the change in */ /* width/positioning that occurred during the hinting process */ @@ -408,6 +451,8 @@ old_lsb = edge1->opos /* - loader->pp1.x */; new_lsb = edge1->pos; + /* remember unhinted values to later account */ + /* for rounding errors */ pp1x_uh = new_lsb - old_lsb; pp2x_uh = edge2->pos + old_rsb; @@ -445,6 +490,8 @@ slot->rsb_delta = loader->pp2.x - pp2x; } } + /* `light' mode uses integer advance widths */ + /* but sets `lsb_delta' and `rsb_delta' */ else { FT_Pos pp1x = loader->pp1.x; diff --git a/Source/ThirdParty/FreeType/src/autofit/afloader.h b/Source/ThirdParty/FreeType/src/autofit/afloader.h index 0062eb9b07..2578abed16 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afloader.h +++ b/Source/ThirdParty/FreeType/src/autofit/afloader.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter glyph loading routines (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afmodule.c b/Source/ThirdParty/FreeType/src/autofit/afmodule.c index f325ebf45e..9d7ba224da 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afmodule.c +++ b/Source/ThirdParty/FreeType/src/autofit/afmodule.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module implementation (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -104,6 +104,19 @@ } +#ifdef FT_CONFIG_OPTION_PIC + +#undef AF_SCRIPT_CLASSES_GET +#define AF_SCRIPT_CLASSES_GET \ + ( GET_PIC( ft_module->library )->af_script_classes ) + +#undef AF_STYLE_CLASSES_GET +#define AF_STYLE_CLASSES_GET \ + ( GET_PIC( ft_module->library )->af_style_classes ) + +#endif + + static FT_Error af_property_set( FT_Module ft_module, const char* property_name, @@ -291,12 +304,10 @@ long nsd = ft_strtol( s, NULL, 10 ); - if ( nsd == 0 ) - module->no_stem_darkening = 0; - else if ( nsd == 1 ) - module->no_stem_darkening = 1; + if ( !nsd ) + module->no_stem_darkening = FALSE; else - return FT_THROW( Invalid_Argument ); + module->no_stem_darkening = TRUE; } else #endif diff --git a/Source/ThirdParty/FreeType/src/autofit/afmodule.h b/Source/ThirdParty/FreeType/src/autofit/afmodule.h index e65db5f5cb..0571d14d59 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afmodule.h +++ b/Source/ThirdParty/FreeType/src/autofit/afmodule.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module implementation (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afpic.c b/Source/ThirdParty/FreeType/src/autofit/afpic.c index 3cbd9168e3..3125e03e27 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afpic.c +++ b/Source/ThirdParty/FreeType/src/autofit/afpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for autofit module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afpic.h b/Source/ThirdParty/FreeType/src/autofit/afpic.h index 98a45a26ba..8cd3392123 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afpic.h +++ b/Source/ThirdParty/FreeType/src/autofit/afpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for autofit module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -69,7 +69,7 @@ FT_BEGIN_HEADER #define GET_PIC( lib ) \ - ( (AFModulePIC*)((lib)->pic_container.autofit) ) + ( (AFModulePIC*)( (lib)->pic_container.autofit ) ) #define AF_SERVICES_GET \ ( GET_PIC( library )->af_services ) diff --git a/Source/ThirdParty/FreeType/src/autofit/afranges.c b/Source/ThirdParty/FreeType/src/autofit/afranges.c index 732f3d1629..7f37eea1e0 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afranges.c +++ b/Source/ThirdParty/FreeType/src/autofit/afranges.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter Unicode script ranges (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -52,8 +52,21 @@ /* not be affected by blue zones, regardless of whether this is a */ /* spacing or no-spacing glyph */ - /* the `ta_xxxx_nonbase_uniranges' ranges must be strict subsets */ - /* of the corresponding `ta_xxxx_uniranges' ranges */ + /* the `af_xxxx_nonbase_uniranges' ranges must be strict subsets */ + /* of the corresponding `af_xxxx_uniranges' ranges */ + + + const AF_Script_UniRangeRec af_adlm_uniranges[] = + { + AF_UNIRANGE_REC( 0x1E900, 0x1E95F ), /* Adlam */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_adlm_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1D944, 0x1E94A ), + AF_UNIRANGE_REC( 0, 0 ) + }; const AF_Script_UniRangeRec af_arab_uniranges[] = @@ -106,6 +119,37 @@ }; + const AF_Script_UniRangeRec af_avst_uniranges[] = + { + AF_UNIRANGE_REC( 0x10B00, 0x10B3F ), /* Avestan */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_avst_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x10B39, 0x10B3F ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_bamu_uniranges[] = + { + AF_UNIRANGE_REC( 0xA6A0, 0xA6FF ), /* Bamum */ +#if 0 + /* The characters in the Bamum supplement are pictograms, */ + /* not (directly) related to the syllabic Bamum script */ + AF_UNIRANGE_REC( 0x16800, 0x16A3F ), /* Bamum Supplement */ +#endif + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_bamu_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xA6F0, 0xA6F1 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_beng_uniranges[] = { AF_UNIRANGE_REC( 0x0980, 0x09FF ), /* Bengali */ @@ -123,6 +167,58 @@ }; + const AF_Script_UniRangeRec af_buhd_uniranges[] = + { + AF_UNIRANGE_REC( 0x1740, 0x175F ), /* Buhid */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_buhd_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1752, 0x1753 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cakm_uniranges[] = + { + AF_UNIRANGE_REC( 0x11100, 0x1114F ), /* Chakma */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cakm_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x11100, 0x11102 ), + AF_UNIRANGE_REC( 0x11127, 0x11134 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cans_uniranges[] = + { + AF_UNIRANGE_REC( 0x1400, 0x167F ), /* Unified Canadian Aboriginal Syllabics */ + AF_UNIRANGE_REC( 0x18B0, 0x18FF ), /* Unified Canadian Aboriginal Syllabics Extended */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cans_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cari_uniranges[] = + { + AF_UNIRANGE_REC( 0x102A0, 0x102DF ), /* Carian */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cari_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cher_uniranges[] = { AF_UNIRANGE_REC( 0x13A0, 0x13FF ), /* Cherokee */ @@ -136,6 +232,31 @@ }; + const AF_Script_UniRangeRec af_copt_uniranges[] = + { + AF_UNIRANGE_REC( 0x2C80, 0x2CFF ), /* Coptic */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_copt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x2CEF, 0x2CF1 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cprt_uniranges[] = + { + AF_UNIRANGE_REC( 0x10800, 0x1083F ), /* Cypriot */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cprt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cyrl_uniranges[] = { AF_UNIRANGE_REC( 0x0400, 0x04FF ), /* Cyrillic */ @@ -187,6 +308,18 @@ }; + const AF_Script_UniRangeRec af_dsrt_uniranges[] = + { + AF_UNIRANGE_REC( 0x10400, 0x1044F ), /* Deseret */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_dsrt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_ethi_uniranges[] = { AF_UNIRANGE_REC( 0x1200, 0x137F ), /* Ethiopic */ @@ -233,6 +366,32 @@ }; + const AF_Script_UniRangeRec af_glag_uniranges[] = + { + AF_UNIRANGE_REC( 0x2C00, 0x2C5F ), /* Glagolitic */ + AF_UNIRANGE_REC( 0x1E000, 0x1E02F ), /* Glagolitic Supplement */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_glag_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1E000, 0x1E02F ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_goth_uniranges[] = + { + AF_UNIRANGE_REC( 0x10330, 0x1034F ), /* Gothic */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_goth_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_grek_uniranges[] = { AF_UNIRANGE_REC( 0x0370, 0x03FF ), /* Greek and Coptic */ @@ -305,6 +464,19 @@ }; + const AF_Script_UniRangeRec af_kali_uniranges[] = + { + AF_UNIRANGE_REC( 0xA900, 0xA92F ), /* Kayah Li */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_kali_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xA926, 0xA92D ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_knda_uniranges[] = { AF_UNIRANGE_REC( 0x0C80, 0x0CFF ), /* Kannada */ @@ -463,6 +635,18 @@ }; + const AF_Script_UniRangeRec af_lisu_uniranges[] = + { + AF_UNIRANGE_REC( 0xA4D0, 0xA4FF ), /* Lisu */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_lisu_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_mlym_uniranges[] = { AF_UNIRANGE_REC( 0x0D00, 0x0D7F ), /* Malayalam */ @@ -480,27 +664,40 @@ const AF_Script_UniRangeRec af_mymr_uniranges[] = { - AF_UNIRANGE_REC( 0x1000, 0x109F ), /* Myanmar */ - AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ), /* Myanmar Extended-B */ - AF_UNIRANGE_REC( 0xAA60, 0xAA7F ), /* Myanmar Extended-A */ - AF_UNIRANGE_REC( 0, 0 ) + AF_UNIRANGE_REC( 0x1000, 0x109F ), /* Myanmar */ + AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ), /* Myanmar Extended-B */ + AF_UNIRANGE_REC( 0xAA60, 0xAA7F ), /* Myanmar Extended-A */ + AF_UNIRANGE_REC( 0, 0 ) }; const AF_Script_UniRangeRec af_mymr_nonbase_uniranges[] = { - AF_UNIRANGE_REC( 0x102D, 0x1030 ), - AF_UNIRANGE_REC( 0x1032, 0x1037 ), - AF_UNIRANGE_REC( 0x103A, 0x103A ), - AF_UNIRANGE_REC( 0x103D, 0x103E ), - AF_UNIRANGE_REC( 0x1058, 0x1059 ), - AF_UNIRANGE_REC( 0x105E, 0x1060 ), - AF_UNIRANGE_REC( 0x1071, 0x1074 ), - AF_UNIRANGE_REC( 0x1082, 0x1082 ), - AF_UNIRANGE_REC( 0x1085, 0x1086 ), - AF_UNIRANGE_REC( 0x108D, 0x108D ), - AF_UNIRANGE_REC( 0xA9E5, 0xA9E5 ), - AF_UNIRANGE_REC( 0xAA7C, 0xAA7C ), - AF_UNIRANGE_REC( 0, 0 ) + AF_UNIRANGE_REC( 0x102D, 0x1030 ), + AF_UNIRANGE_REC( 0x1032, 0x1037 ), + AF_UNIRANGE_REC( 0x103A, 0x103A ), + AF_UNIRANGE_REC( 0x103D, 0x103E ), + AF_UNIRANGE_REC( 0x1058, 0x1059 ), + AF_UNIRANGE_REC( 0x105E, 0x1060 ), + AF_UNIRANGE_REC( 0x1071, 0x1074 ), + AF_UNIRANGE_REC( 0x1082, 0x1082 ), + AF_UNIRANGE_REC( 0x1085, 0x1086 ), + AF_UNIRANGE_REC( 0x108D, 0x108D ), + AF_UNIRANGE_REC( 0xA9E5, 0xA9E5 ), + AF_UNIRANGE_REC( 0xAA7C, 0xAA7C ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_nkoo_uniranges[] = + { + AF_UNIRANGE_REC( 0x07C0, 0x07FF ), /* N'Ko */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_nkoo_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x07EB, 0x07F5 ), + AF_UNIRANGE_REC( 0, 0 ) }; @@ -515,6 +712,80 @@ }; + const AF_Script_UniRangeRec af_olck_uniranges[] = + { + AF_UNIRANGE_REC( 0x1C50, 0x1C7F ), /* Ol Chiki */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_olck_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_orkh_uniranges[] = + { + AF_UNIRANGE_REC( 0x10C00, 0x10C4F ), /* Old Turkic */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_orkh_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_osge_uniranges[] = + { + AF_UNIRANGE_REC( 0x104B0, 0x104FF ), /* Osage */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_osge_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_osma_uniranges[] = + { + AF_UNIRANGE_REC( 0x10480, 0x104AF ), /* Osmanya */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_osma_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_saur_uniranges[] = + { + AF_UNIRANGE_REC( 0xA880, 0xA8DF ), /* Saurashtra */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_saur_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xA880, 0xA881 ), + AF_UNIRANGE_REC( 0xA8B4, 0xA8C5 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_shaw_uniranges[] = + { + AF_UNIRANGE_REC( 0x10450, 0x1047F ), /* Shavian */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_shaw_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_sinh_uniranges[] = { AF_UNIRANGE_REC( 0x0D80, 0x0DFF ), /* Sinhala */ @@ -529,6 +800,21 @@ }; + const AF_Script_UniRangeRec af_sund_uniranges[] = + { + AF_UNIRANGE_REC( 0x1B80, 0x1BBF ), /* Sundanese */ + AF_UNIRANGE_REC( 0x1CC0, 0x1CCF ), /* Sundanese Supplement */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_sund_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1B80, 0x1B82 ), + AF_UNIRANGE_REC( 0x1BA1, 0x1BAD ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_taml_uniranges[] = { AF_UNIRANGE_REC( 0x0B80, 0x0BFF ), /* Tamil */ @@ -544,6 +830,23 @@ }; + const AF_Script_UniRangeRec af_tavt_uniranges[] = + { + AF_UNIRANGE_REC( 0xAA80, 0xAADF ), /* Tai Viet */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_tavt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xAAB0, 0xAAB0 ), + AF_UNIRANGE_REC( 0xAAB2, 0xAAB4 ), + AF_UNIRANGE_REC( 0xAAB7, 0xAAB8 ), + AF_UNIRANGE_REC( 0xAABE, 0xAABF ), + AF_UNIRANGE_REC( 0xAAC1, 0xAAC1 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_telu_uniranges[] = { AF_UNIRANGE_REC( 0x0C00, 0x0C7F ), /* Telugu */ @@ -575,6 +878,30 @@ }; + const AF_Script_UniRangeRec af_tfng_uniranges[] = + { + AF_UNIRANGE_REC( 0x2D30, 0x2D7F ), /* Tifinagh */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_tfng_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_vaii_uniranges[] = + { + AF_UNIRANGE_REC( 0xA500, 0xA63F ), /* Vai */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_vaii_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + #ifdef AF_CONFIG_OPTION_INDIC const AF_Script_UniRangeRec af_limb_uniranges[] = @@ -610,21 +937,6 @@ }; - const AF_Script_UniRangeRec af_sund_uniranges[] = - { - AF_UNIRANGE_REC( 0x1B80, 0x1BBF ), /* Sundanese */ - AF_UNIRANGE_REC( 0x1CC0, 0x1CCF ), /* Sundanese Supplement */ - AF_UNIRANGE_REC( 0, 0 ) - }; - - const AF_Script_UniRangeRec af_sund_nonbase_uniranges[] = - { - AF_UNIRANGE_REC( 0x1B80, 0x1B82 ), - AF_UNIRANGE_REC( 0x1BA1, 0x1BAD ), - AF_UNIRANGE_REC( 0, 0 ) - }; - - const AF_Script_UniRangeRec af_sylo_uniranges[] = { AF_UNIRANGE_REC( 0xA800, 0xA82F ), /* Syloti Nagri */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afranges.h b/Source/ThirdParty/FreeType/src/autofit/afranges.h index 1a0e4b1535..72d9eaad2c 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afranges.h +++ b/Source/ThirdParty/FreeType/src/autofit/afranges.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter Unicode script ranges (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afscript.h b/Source/ThirdParty/FreeType/src/autofit/afscript.h index cffe59105d..7547a9e6f9 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afscript.h +++ b/Source/ThirdParty/FreeType/src/autofit/afscript.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter scripts (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,12 @@ /* use `HB_SCRIPT_INVALID' as the HarfBuzz script name tag for */ /* them. */ + SCRIPT( adlm, ADLM, + "Adlam", + HB_SCRIPT_ADLAM, + HINTING_BOTTOM_TO_TOP, + "\xF0\x9E\xA4\x8C \xF0\x9E\xA4\xAE" ) /* 𞤌 𞤮 */ + SCRIPT( arab, ARAB, "Arabic", HB_SCRIPT_ARABIC, @@ -42,6 +48,18 @@ HINTING_BOTTOM_TO_TOP, "\xD5\xBD \xD5\x8D" ) /* ս Ս */ + SCRIPT( avst, AVST, + "Avestan", + HB_SCRIPT_AVESTAN, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\xAC\x9A" ) /* 𐬚 */ + + SCRIPT( bamu, BAMU, + "Bamum", + HB_SCRIPT_BAMUM, + HINTING_BOTTOM_TO_TOP, + "\xEA\x9B\x81 \xEA\x9B\xAF" ) /* ꛁ ꛯ */ + /* there are no simple forms for letters; we thus use two digit shapes */ SCRIPT( beng, BENG, "Bengali", @@ -49,12 +67,48 @@ HINTING_TOP_TO_BOTTOM, "\xE0\xA7\xA6 \xE0\xA7\xAA" ) /* ০ ৪ */ + SCRIPT( buhd, BUHD, + "Buhid", + HB_SCRIPT_BUHID, + HINTING_BOTTOM_TO_TOP, + "\xE1\x9D\x8B \xE1\x9D\x8F" ) /* ᝋ ᝏ */ + + SCRIPT( cakm, CAKM, + "Chakma", + HB_SCRIPT_CHAKMA, + HINTING_BOTTOM_TO_TOP, + "\xF0\x91\x84\xA4 \xF0\x91\x84\x89 \xF0\x91\x84\x9B" ) /* 𑄤 𑄉 𑄛 */ + + SCRIPT( cans, CANS, + "Canadian Syllabics", + HB_SCRIPT_CANADIAN_SYLLABICS, + HINTING_BOTTOM_TO_TOP, + "\xE1\x91\x8C \xE1\x93\x9A" ) /* ᑌ ᓚ */ + + SCRIPT( cari, CARI, + "Carian", + HB_SCRIPT_CARIAN, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x8A\xAB \xF0\x90\x8B\x89" ) /* 𐊫 𐋉 */ + SCRIPT( cher, CHER, "Cherokee", HB_SCRIPT_CHEROKEE, HINTING_BOTTOM_TO_TOP, "\xE1\x8E\xA4 \xE1\x8F\x85 \xEA\xAE\x95" ) /* Ꭴ Ꮕ ꮕ */ + SCRIPT( copt, COPT, + "Coptic", + HB_SCRIPT_COPTIC, + HINTING_BOTTOM_TO_TOP, + "\xE2\xB2\x9E \xE2\xB2\x9F" ) /* Ⲟ ⲟ */ + + SCRIPT( cprt, CPRT, + "Cypriot", + HB_SCRIPT_CYPRIOT, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\xA0\x85 \xF0\x90\xA0\xA3" ) /* 𐠅 𐠣 */ + SCRIPT( cyrl, CYRL, "Cyrillic", HB_SCRIPT_CYRILLIC, @@ -67,6 +121,12 @@ HINTING_TOP_TO_BOTTOM, "\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */ + SCRIPT( dsrt, DSRT, + "Deseret", + HB_SCRIPT_DESERET, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x90\x84 \xF0\x90\x90\xAC" ) /* 𐐄 𐐬 */ + SCRIPT( ethi, ETHI, "Ethiopic", HB_SCRIPT_ETHIOPIC, @@ -85,6 +145,18 @@ HINTING_BOTTOM_TO_TOP, "\xE1\x82\xB6 \xE1\x82\xB1 \xE2\xB4\x99" ) /* Ⴖ Ⴑ ⴙ */ + SCRIPT( glag, GLAG, + "Glagolitic", + HB_SCRIPT_GLAGOLITIC, + HINTING_BOTTOM_TO_TOP, + "\xE2\xB0\x95 \xE2\xB1\x85" ) /* Ⱅ ⱅ */ + + SCRIPT( goth, GOTH, + "Gothic", + HB_SCRIPT_GOTHIC, + HINTING_TOP_TO_BOTTOM, + "\xF0\x90\x8C\xB4 \xF0\x90\x8C\xBE \xF0\x90\x8D\x83" ) /* 𐌴 𐌾 𐍃 */ + SCRIPT( grek, GREK, "Greek", HB_SCRIPT_GREEK, @@ -109,6 +181,12 @@ HINTING_BOTTOM_TO_TOP, "\xD7\x9D" ) /* ם */ + SCRIPT( kali, KALI, + "Kayah Li", + HB_SCRIPT_KAYAH_LI, + HINTING_BOTTOM_TO_TOP, + "\xEA\xA4\x8D \xEA\xA4\x80" ) /* ꤍ ꤀ */ + SCRIPT( knda, KNDA, "Kannada", HB_SCRIPT_KANNADA, @@ -153,6 +231,12 @@ HINTING_BOTTOM_TO_TOP, "\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */ + SCRIPT( lisu, LISU, + "Lisu", + HB_SCRIPT_LISU, + HINTING_BOTTOM_TO_TOP, + "\xEA\x93\xB3" ) /* ꓳ */ + SCRIPT( mlym, MLYM, "Malayalam", HB_SCRIPT_MALAYALAM, @@ -165,18 +249,67 @@ HINTING_BOTTOM_TO_TOP, "\xE1\x80\x9D \xE1\x80\x84 \xE1\x80\x82" ) /* ဝ င ဂ */ + SCRIPT( nkoo, NKOO, + "N'Ko", + HB_SCRIPT_NKO, + HINTING_BOTTOM_TO_TOP, + "\xDF\x8B \xDF\x80" ) /* ߋ ߀ */ + SCRIPT( none, NONE, "no script", HB_SCRIPT_INVALID, HINTING_BOTTOM_TO_TOP, "" ) + SCRIPT( olck, OLCK, + "Ol Chiki", + HB_SCRIPT_OL_CHIKI, + HINTING_BOTTOM_TO_TOP, + "\xE1\xB1\x9B" ) /* ᱛ */ + + SCRIPT( orkh, ORKH, + "Old Turkic", + HB_SCRIPT_OLD_TURKIC, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\xB0\x97" ) /* 𐰗 */ + + SCRIPT( osge, OSGE, + "Osage", + HB_SCRIPT_OSAGE, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x93\x82 \xF0\x90\x93\xAA" ) /* 𐓂 𐓪 */ + + SCRIPT( osma, OSMA, + "Osmanya", + HB_SCRIPT_OSMANYA, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x92\x86 \xF0\x90\x92\xA0" ) /* 𐒆 𐒠 */ + + SCRIPT( saur, SAUR, + "Saurashtra", + HB_SCRIPT_SAURASHTRA, + HINTING_BOTTOM_TO_TOP, + "\xEA\xA2\x9D \xEA\xA3\x90" ) /* ꢝ ꣐ */ + + SCRIPT( shaw, SHAW, + "Shavian", + HB_SCRIPT_SHAVIAN, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x91\xB4" ) /* 𐑴 */ + SCRIPT( sinh, SINH, "Sinhala", HB_SCRIPT_SINHALA, HINTING_BOTTOM_TO_TOP, "\xE0\xB6\xA7" ) /* ට */ + /* only digit zero has a simple (round) shape in the Sundanese script */ + SCRIPT( sund, SUND, + "Sundanese", + HB_SCRIPT_SUNDANESE, + HINTING_BOTTOM_TO_TOP, + "\xE1\xAE\xB0" ) /* ᮰ */ + /* only digit zero has a simple (round) shape in the Tamil script */ SCRIPT( taml, TAML, "Tamil", @@ -184,6 +317,12 @@ HINTING_BOTTOM_TO_TOP, "\xE0\xAF\xA6" ) /* ௦ */ + SCRIPT( tavt, TAVT, + "Tai Viet", + HB_SCRIPT_TAI_VIET, + HINTING_BOTTOM_TO_TOP, + "\xEA\xAA\x92 \xEA\xAA\xAB" ) /* ꪒ ꪫ */ + /* there are no simple forms for letters; we thus use two digit shapes */ SCRIPT( telu, TELU, "Telugu", @@ -197,6 +336,18 @@ HINTING_BOTTOM_TO_TOP, "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๐ */ + SCRIPT( tfng, TFNG, + "Tifinagh", + HB_SCRIPT_TIFINAGH, + HINTING_BOTTOM_TO_TOP, + "\xE2\xB5\x94" ) /* ⵔ */ + + SCRIPT( vaii, VAII, + "Vai", + HB_SCRIPT_VAI, + HINTING_BOTTOM_TO_TOP, + "\xEA\x98\x93 \xEA\x96\x9C \xEA\x96\xB4" ) /* ꘓ ꖜ ꖴ */ + #ifdef AF_CONFIG_OPTION_INDIC SCRIPT( limb, LIMB, @@ -211,12 +362,6 @@ HINTING_BOTTOM_TO_TOP, "o" ) /* XXX */ - SCRIPT( sund, SUND, - "Sundanese", - HB_SCRIPT_SUNDANESE, - HINTING_BOTTOM_TO_TOP, - "o" ) /* XXX */ - SCRIPT( sylo, SYLO, "Syloti Nagri", HB_SCRIPT_SYLOTI_NAGRI, diff --git a/Source/ThirdParty/FreeType/src/autofit/afshaper.c b/Source/ThirdParty/FreeType/src/autofit/afshaper.c index 6d13b65859..da92fad3ed 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afshaper.c +++ b/Source/ThirdParty/FreeType/src/autofit/afshaper.c @@ -4,7 +4,7 @@ /* */ /* HarfBuzz interface for accessing OpenType features (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afshaper.h b/Source/ThirdParty/FreeType/src/autofit/afshaper.h index 0d41f78762..9185d19003 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afshaper.h +++ b/Source/ThirdParty/FreeType/src/autofit/afshaper.h @@ -4,7 +4,7 @@ /* */ /* HarfBuzz interface for accessing OpenType features (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afstyles.h b/Source/ThirdParty/FreeType/src/autofit/afstyles.h index e83a95bb59..a5e13d8944 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afstyles.h +++ b/Source/ThirdParty/FreeType/src/autofit/afstyles.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter styles (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -83,6 +83,13 @@ DEFAULT ) + STYLE( adlm_dflt, ADLM_DFLT, + "Adlam default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_ADLM, + AF_BLUE_STRINGSET_ADLM, + AF_COVERAGE_DEFAULT ) + STYLE( arab_dflt, ARAB_DFLT, "Arabic default style", AF_WRITING_SYSTEM_LATIN, @@ -97,6 +104,20 @@ AF_BLUE_STRINGSET_ARMN, AF_COVERAGE_DEFAULT ) + STYLE( avst_dflt, AVST_DFLT, + "Avestan default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_AVST, + AF_BLUE_STRINGSET_AVST, + AF_COVERAGE_DEFAULT ) + + STYLE( bamu_dflt, BAMU_DFLT, + "Bamum default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_BAMU, + AF_BLUE_STRINGSET_BAMU, + AF_COVERAGE_DEFAULT ) + STYLE( beng_dflt, BENG_DFLT, "Bengali default style", AF_WRITING_SYSTEM_LATIN, @@ -104,6 +125,34 @@ AF_BLUE_STRINGSET_BENG, AF_COVERAGE_DEFAULT ) + STYLE( buhd_dflt, BUHD_DFLT, + "Buhid default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_BUHD, + AF_BLUE_STRINGSET_BUHD, + AF_COVERAGE_DEFAULT ) + + STYLE( cakm_dflt, CAKM_DFLT, + "Chakma default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CAKM, + AF_BLUE_STRINGSET_CAKM, + AF_COVERAGE_DEFAULT ) + + STYLE( cans_dflt, CANS_DFLT, + "Canadian Syllabics default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CANS, + AF_BLUE_STRINGSET_CANS, + AF_COVERAGE_DEFAULT ) + + STYLE( cari_dflt, CARI_DFLT, + "Carian default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CARI, + AF_BLUE_STRINGSET_CARI, + AF_COVERAGE_DEFAULT ) + STYLE( cher_dflt, CHER_DFLT, "Cherokee default style", AF_WRITING_SYSTEM_LATIN, @@ -111,6 +160,20 @@ AF_BLUE_STRINGSET_CHER, AF_COVERAGE_DEFAULT ) + STYLE( copt_dflt, COPT_DFLT, + "Coptic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_COPT, + AF_BLUE_STRINGSET_COPT, + AF_COVERAGE_DEFAULT ) + + STYLE( cprt_dflt, CPRT_DFLT, + "Cypriot default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CPRT, + AF_BLUE_STRINGSET_CPRT, + AF_COVERAGE_DEFAULT ) + META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" ) STYLE( deva_dflt, DEVA_DFLT, @@ -120,6 +183,13 @@ AF_BLUE_STRINGSET_DEVA, AF_COVERAGE_DEFAULT ) + STYLE( dsrt_dflt, DSRT_DFLT, + "Deseret default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_DSRT, + AF_BLUE_STRINGSET_DSRT, + AF_COVERAGE_DEFAULT ) + STYLE( ethi_dflt, ETHI_DFLT, "Ethiopic default style", AF_WRITING_SYSTEM_LATIN, @@ -141,6 +211,20 @@ AF_BLUE_STRINGSET_GEOK, AF_COVERAGE_DEFAULT ) + STYLE( glag_dflt, GLAG_DFLT, + "Glagolitic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_GLAG, + AF_BLUE_STRINGSET_GLAG, + AF_COVERAGE_DEFAULT ) + + STYLE( goth_dflt, GOTH_DFLT, + "Gothic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_GOTH, + AF_BLUE_STRINGSET_GOTH, + AF_COVERAGE_DEFAULT ) + META_STYLE_LATIN( grek, GREK, "Greek" ) STYLE( gujr_dflt, GUJR_DFLT, @@ -164,6 +248,13 @@ AF_BLUE_STRINGSET_HEBR, AF_COVERAGE_DEFAULT ) + STYLE( kali_dflt, KALI_DFLT, + "Kayah Li default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_KALI, + AF_BLUE_STRINGSET_KALI, + AF_COVERAGE_DEFAULT ) + STYLE( knda_dflt, KNDA_DFLT, "Kannada default style", AF_WRITING_SYSTEM_LATIN, @@ -217,6 +308,13 @@ AF_COVERAGE_DEFAULT ) #endif + STYLE( lisu_dflt, LISU_DFLT, + "Lisu default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_LISU, + AF_BLUE_STRINGSET_LISU, + AF_COVERAGE_DEFAULT ) + STYLE( mlym_dflt, MLYM_DFLT, "Malayalam default style", AF_WRITING_SYSTEM_LATIN, @@ -231,6 +329,13 @@ AF_BLUE_STRINGSET_MYMR, AF_COVERAGE_DEFAULT ) + STYLE( nkoo_dflt, NKOO_DFLT, + "N'Ko default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_NKOO, + AF_BLUE_STRINGSET_NKOO, + AF_COVERAGE_DEFAULT ) + STYLE( none_dflt, NONE_DFLT, "no style", AF_WRITING_SYSTEM_DUMMY, @@ -238,6 +343,48 @@ AF_BLUE_STRINGSET_NONE, AF_COVERAGE_DEFAULT ) + STYLE( olck_dflt, OLCK_DFLT, + "Ol Chiki default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_OLCK, + AF_BLUE_STRINGSET_OLCK, + AF_COVERAGE_DEFAULT ) + + STYLE( orkh_dflt, ORKH_DFLT, + "Old Turkic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_ORKH, + AF_BLUE_STRINGSET_ORKH, + AF_COVERAGE_DEFAULT ) + + STYLE( osge_dflt, OSGE_DFLT, + "Osage default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_OSGE, + AF_BLUE_STRINGSET_OSGE, + AF_COVERAGE_DEFAULT ) + + STYLE( osma_dflt, OSMA_DFLT, + "Osmanya default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_OSMA, + AF_BLUE_STRINGSET_OSMA, + AF_COVERAGE_DEFAULT ) + + STYLE( saur_dflt, SAUR_DFLT, + "Saurashtra default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_SAUR, + AF_BLUE_STRINGSET_SAUR, + AF_COVERAGE_DEFAULT ) + + STYLE( shaw_dflt, SHAW_DFLT, + "Shavian default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_SHAW, + AF_BLUE_STRINGSET_SHAW, + AF_COVERAGE_DEFAULT ) + STYLE( sinh_dflt, SINH_DFLT, "Sinhala default style", AF_WRITING_SYSTEM_LATIN, @@ -245,6 +392,13 @@ AF_BLUE_STRINGSET_SINH, AF_COVERAGE_DEFAULT ) + STYLE( sund_dflt, SUND_DFLT, + "Sundanese default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_SUND, + AF_BLUE_STRINGSET_SUND, + AF_COVERAGE_DEFAULT ) + STYLE( taml_dflt, TAML_DFLT, "Tamil default style", AF_WRITING_SYSTEM_LATIN, @@ -252,6 +406,13 @@ AF_BLUE_STRINGSET_TAML, AF_COVERAGE_DEFAULT ) + STYLE( tavt_dflt, TAVT_DFLT, + "Tai Viet default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_TAVT, + AF_BLUE_STRINGSET_TAVT, + AF_COVERAGE_DEFAULT ) + STYLE( telu_dflt, TELU_DFLT, "Telugu default style", AF_WRITING_SYSTEM_LATIN, @@ -266,6 +427,20 @@ AF_BLUE_STRINGSET_THAI, AF_COVERAGE_DEFAULT ) + STYLE( tfng_dflt, TFNG_DFLT, + "Tifinagh default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_TFNG, + AF_BLUE_STRINGSET_TFNG, + AF_COVERAGE_DEFAULT ) + + STYLE( vaii_dflt, VAII_DFLT, + "Vai default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_VAII, + AF_BLUE_STRINGSET_VAII, + AF_COVERAGE_DEFAULT ) + #ifdef AF_CONFIG_OPTION_INDIC /* no blue stringset support for the Indic writing system yet */ @@ -280,7 +455,6 @@ STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" ) STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" ) - STYLE_DEFAULT_INDIC( sund, SUND, "Sundanese" ) STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" ) STYLE_DEFAULT_INDIC( tibt, TIBT, "Tibetan" ) diff --git a/Source/ThirdParty/FreeType/src/autofit/aftypes.h b/Source/ThirdParty/FreeType/src/autofit/aftypes.h index 61b6b12bb8..718dab70b6 100644 --- a/Source/ThirdParty/FreeType/src/autofit/aftypes.h +++ b/Source/ThirdParty/FreeType/src/autofit/aftypes.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter types (specification only). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -575,6 +575,7 @@ extern void* _af_debug_hints; m_init, \ m_scale, \ m_done, \ + m_stdw, \ h_init, \ h_apply ) \ FT_LOCAL_DEF( void ) \ diff --git a/Source/ThirdParty/FreeType/src/autofit/afwarp.c b/Source/ThirdParty/FreeType/src/autofit/afwarp.c index ce1806c9d3..f99aa6d987 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afwarp.c +++ b/Source/ThirdParty/FreeType/src/autofit/afwarp.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter warping algorithm (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -98,7 +98,6 @@ if ( xx1min + w < warper->x2min ) xx1min = warper->x2min - w; - xx1max = warper->x1max; if ( xx1max + w > warper->x2max ) xx1max = warper->x2max - w; diff --git a/Source/ThirdParty/FreeType/src/autofit/afwarp.h b/Source/ThirdParty/FreeType/src/autofit/afwarp.h index 6d96f86d73..2e85cbd851 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afwarp.h +++ b/Source/ThirdParty/FreeType/src/autofit/afwarp.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter warping algorithm (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/afwrtsys.h b/Source/ThirdParty/FreeType/src/autofit/afwrtsys.h index 842f4921a4..86749a2a83 100644 --- a/Source/ThirdParty/FreeType/src/autofit/afwrtsys.h +++ b/Source/ThirdParty/FreeType/src/autofit/afwrtsys.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter writing systems (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/autofit/autofit.c b/Source/ThirdParty/FreeType/src/autofit/autofit.c index dda9aeb6d7..bbedad7b5f 100644 --- a/Source/ThirdParty/FreeType/src/autofit/autofit.c +++ b/Source/ThirdParty/FreeType/src/autofit/autofit.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,29 +18,22 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> -#include "afpic.c" + #include "afangles.c" #include "afblue.c" +#include "afcjk.c" +#include "afdummy.c" #include "afglobal.c" #include "afhints.c" - -#include "afranges.c" - -#include "afdummy.c" +#include "afindic.c" #include "aflatin.c" -#ifdef FT_OPTION_AUTOFIT2 #include "aflatin2.c" -#endif -#include "afcjk.c" -#include "afindic.c" - -#include "afshaper.c" - #include "afloader.c" #include "afmodule.c" - -#ifdef AF_CONFIG_OPTION_USE_WARPER +#include "afpic.c" +#include "afranges.c" +#include "afshaper.c" #include "afwarp.c" -#endif + /* END */ diff --git a/Source/ThirdParty/FreeType/src/base/basepic.c b/Source/ThirdParty/FreeType/src/base/basepic.c index f2cea90d7c..57fb8169ad 100644 --- a/Source/ThirdParty/FreeType/src/base/basepic.c +++ b/Source/ThirdParty/FreeType/src/base/basepic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for base. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/basepic.h b/Source/ThirdParty/FreeType/src/base/basepic.h index a1a75a0bad..258d4ce2ba 100644 --- a/Source/ThirdParty/FreeType/src/base/basepic.h +++ b/Source/ThirdParty/FreeType/src/base/basepic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for base. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftadvanc.c b/Source/ThirdParty/FreeType/src/base/ftadvanc.c index 59c74502c9..1557607fc5 100644 --- a/Source/ThirdParty/FreeType/src/base/ftadvanc.c +++ b/Source/ThirdParty/FreeType/src/base/ftadvanc.c @@ -4,7 +4,7 @@ /* */ /* Quick computation of advance widths (body). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftapi.c b/Source/ThirdParty/FreeType/src/base/ftapi.c index b94c3eb9fb..4262d37e39 100644 --- a/Source/ThirdParty/FreeType/src/base/ftapi.c +++ b/Source/ThirdParty/FreeType/src/base/ftapi.c @@ -4,7 +4,7 @@ /* */ /* The FreeType compatibility functions (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -38,7 +38,7 @@ /*************************************************************************/ /*************************************************************************/ - /* backwards compatibility API */ + /* backward compatibility API */ FT_BASE_DEF( void ) FT_New_Memory_Stream( FT_Library library, diff --git a/Source/ThirdParty/FreeType/src/base/ftbase.c b/Source/ThirdParty/FreeType/src/base/ftbase.c index ab1af6f9f3..55f7359942 100644 --- a/Source/ThirdParty/FreeType/src/base/ftbase.c +++ b/Source/ThirdParty/FreeType/src/base/ftbase.c @@ -4,7 +4,7 @@ /* */ /* Single object library component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,26 +17,23 @@ #include <ft2build.h> - #define FT_MAKE_OPTION_SINGLE_OBJECT -#include "ftpic.c" #include "basepic.c" #include "ftadvanc.c" #include "ftcalc.c" #include "ftdbgmem.c" #include "ftgloadr.c" #include "fthash.c" +#include "ftmac.c" #include "ftobjs.c" #include "ftoutln.c" +#include "ftpic.c" #include "ftrfork.c" #include "ftsnames.c" #include "ftstream.c" #include "fttrigon.c" #include "ftutil.c" -#ifdef FT_MACINTOSH -#include "ftmac.c" -#endif /* END */ diff --git a/Source/ThirdParty/FreeType/src/base/ftbase.h b/Source/ThirdParty/FreeType/src/base/ftbase.h index 717fdaae24..2072284f06 100644 --- a/Source/ThirdParty/FreeType/src/base/ftbase.h +++ b/Source/ThirdParty/FreeType/src/base/ftbase.h @@ -4,7 +4,7 @@ /* */ /* The FreeType private functions used in base module (specification). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2017 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftbbox.c b/Source/ThirdParty/FreeType/src/base/ftbbox.c index 804dc9058a..6e19da63cb 100644 --- a/Source/ThirdParty/FreeType/src/base/ftbbox.c +++ b/Source/ThirdParty/FreeType/src/base/ftbbox.c @@ -4,7 +4,7 @@ /* */ /* FreeType bbox computation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/Source/ThirdParty/FreeType/src/base/ftbdf.c b/Source/ThirdParty/FreeType/src/base/ftbdf.c index 4aafc2b98e..40f0ca2bb8 100644 --- a/Source/ThirdParty/FreeType/src/base/ftbdf.c +++ b/Source/ThirdParty/FreeType/src/base/ftbdf.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing BDF-specific strings (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftbitmap.c b/Source/ThirdParty/FreeType/src/base/ftbitmap.c index 533e57a70e..88c88c4c1b 100644 --- a/Source/ThirdParty/FreeType/src/base/ftbitmap.c +++ b/Source/ThirdParty/FreeType/src/base/ftbitmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility functions for bitmaps (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftcalc.c b/Source/ThirdParty/FreeType/src/base/ftcalc.c index 1c23922225..f0525502f3 100644 --- a/Source/ThirdParty/FreeType/src/base/ftcalc.c +++ b/Source/ThirdParty/FreeType/src/base/ftcalc.c @@ -4,7 +4,7 @@ /* */ /* Arithmetic computations (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftcid.c b/Source/ThirdParty/FreeType/src/base/ftcid.c index 251bbd009a..398396b845 100644 --- a/Source/ThirdParty/FreeType/src/base/ftcid.c +++ b/Source/ThirdParty/FreeType/src/base/ftcid.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing CID font information. */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* Derek Clegg and Michael Toftdal. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftdbgmem.c b/Source/ThirdParty/FreeType/src/base/ftdbgmem.c index fcdceefd69..242246bfd1 100644 --- a/Source/ThirdParty/FreeType/src/base/ftdbgmem.c +++ b/Source/ThirdParty/FreeType/src/base/ftdbgmem.c @@ -4,7 +4,7 @@ /* */ /* Memory debugger (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftdebug.c b/Source/ThirdParty/FreeType/src/base/ftdebug.c index 40925d14a0..20c617089f 100644 --- a/Source/ThirdParty/FreeType/src/base/ftdebug.c +++ b/Source/ThirdParty/FreeType/src/base/ftdebug.c @@ -4,7 +4,7 @@ /* */ /* Debugging and logging component (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftfntfmt.c b/Source/ThirdParty/FreeType/src/base/ftfntfmt.c index c6eb3190c6..dcbeba0053 100644 --- a/Source/ThirdParty/FreeType/src/base/ftfntfmt.c +++ b/Source/ThirdParty/FreeType/src/base/ftfntfmt.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file for font formats (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftfstype.c b/Source/ThirdParty/FreeType/src/base/ftfstype.c index ae56c8fc8d..cec4fb3025 100644 --- a/Source/ThirdParty/FreeType/src/base/ftfstype.c +++ b/Source/ThirdParty/FreeType/src/base/ftfstype.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file to access FSType data (body). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftgasp.c b/Source/ThirdParty/FreeType/src/base/ftgasp.c index e38e55b6c0..477b72558c 100644 --- a/Source/ThirdParty/FreeType/src/base/ftgasp.c +++ b/Source/ThirdParty/FreeType/src/base/ftgasp.c @@ -4,7 +4,7 @@ /* */ /* Access of TrueType's `gasp' table (body). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftgloadr.c b/Source/ThirdParty/FreeType/src/base/ftgloadr.c index c4f0ff70f4..8134003b4b 100644 --- a/Source/ThirdParty/FreeType/src/base/ftgloadr.c +++ b/Source/ThirdParty/FreeType/src/base/ftgloadr.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftglyph.c b/Source/ThirdParty/FreeType/src/base/ftglyph.c index d336b1c12c..9bfb330508 100644 --- a/Source/ThirdParty/FreeType/src/base/ftglyph.c +++ b/Source/ThirdParty/FreeType/src/base/ftglyph.c @@ -4,7 +4,7 @@ /* */ /* FreeType convenience functions to handle glyphs (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftgxval.c b/Source/ThirdParty/FreeType/src/base/ftgxval.c index 6667b371a1..ff24d336df 100644 --- a/Source/ThirdParty/FreeType/src/base/ftgxval.c +++ b/Source/ThirdParty/FreeType/src/base/ftgxval.c @@ -2,9 +2,9 @@ /* */ /* ftgxval.c */ /* */ -/* FreeType API for validating TrueTyepGX/AAT tables (body). */ +/* FreeType API for validating TrueTypeGX/AAT tables (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Masatake YAMATO, Redhat K.K, */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/base/ftinit.c b/Source/ThirdParty/FreeType/src/base/ftinit.c index 02ef938d5e..b3b08fa541 100644 --- a/Source/ThirdParty/FreeType/src/base/ftinit.c +++ b/Source/ThirdParty/FreeType/src/base/ftinit.c @@ -4,7 +4,7 @@ /* */ /* FreeType initialization layer (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -230,31 +230,10 @@ #define MAX_LENGTH 128 - /* - * Set default properties derived from the `FREETYPE_PROPERTIES' - * environment variable. - * - * `FREETYPE_PROPERTIES' has the following syntax form (broken here into - * multiple lines for better readability) - * - * <optional whitespace> - * <module-name1> ':' - * <property-name1> '=' <property-value1> - * <whitespace> - * <module-name2> ':' - * <property-name2> '=' <property-value2> - * ... - * - * Example: - * - * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ - * cff:no-stem-darkening=1 \ - * autofitter:warping=1 - * - */ - - static void - ft_set_default_properties( FT_Library library ) + /* documentation is in ftmodapi.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Default_Properties( FT_Library library ) { const char* env; const char* p; @@ -326,8 +305,8 @@ #else - static void - ft_set_default_properties( FT_Library library ) + FT_EXPORT_DEF( void ) + FT_Set_Default_Properties( FT_Library library ) { FT_UNUSED( library ); } @@ -365,7 +344,7 @@ else FT_Add_Default_Modules( *alibrary ); - ft_set_default_properties( *alibrary ); + FT_Set_Default_Properties( *alibrary ); return error; } diff --git a/Source/ThirdParty/FreeType/src/base/ftlcdfil.c b/Source/ThirdParty/FreeType/src/base/ftlcdfil.c index 8bcbed7aab..611b39f570 100644 --- a/Source/ThirdParty/FreeType/src/base/ftlcdfil.c +++ b/Source/ThirdParty/FreeType/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for color filtering of subpixel bitmap glyphs (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,14 +30,13 @@ #define USE_LEGACY /* FIR filter used by the default and light filters */ - static void - _ft_lcd_filter_fir( FT_Bitmap* bitmap, - FT_Render_Mode mode, - FT_Library library ) + FT_BASE( void ) + ft_lcd_filter_fir( FT_Bitmap* bitmap, + FT_Render_Mode mode, + FT_LcdFiveTapFilter weights ) { - FT_Byte* weights = library->lcd_weights; - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; + FT_UInt width = (FT_UInt)bitmap->width; + FT_UInt height = (FT_UInt)bitmap->rows; /* horizontal in-place FIR filter */ @@ -176,7 +175,7 @@ static void _ft_lcd_filter_legacy( FT_Bitmap* bitmap, FT_Render_Mode mode, - FT_Library library ) + FT_Byte* weights ) { FT_UInt width = (FT_UInt)bitmap->width; FT_UInt height = (FT_UInt)bitmap->rows; @@ -189,7 +188,7 @@ { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } }; - FT_UNUSED( library ); + FT_UNUSED( weights ); /* horizontal in-place intra-pixel filter */ @@ -295,8 +294,8 @@ if ( !weights ) return FT_THROW( Invalid_Argument ); - ft_memcpy( library->lcd_weights, weights, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; + ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; library->lcd_extra = 2; return FT_Err_Ok; @@ -307,10 +306,10 @@ FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) { - static const FT_Byte default_filter[5] = - { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; - static const FT_Byte light_filter[5] = - { 0x00, 0x55, 0x56, 0x55, 0x00 }; + static const FT_LcdFiveTapFilter default_weights = + { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; + static const FT_LcdFiveTapFilter light_weights = + { 0x00, 0x55, 0x56, 0x55, 0x00 }; if ( !library ) @@ -324,14 +323,18 @@ break; case FT_LCD_FILTER_DEFAULT: - ft_memcpy( library->lcd_weights, default_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; + ft_memcpy( library->lcd_weights, + default_weights, + FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; library->lcd_extra = 2; break; case FT_LCD_FILTER_LIGHT: - ft_memcpy( library->lcd_weights, light_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; + ft_memcpy( library->lcd_weights, + light_weights, + FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; library->lcd_extra = 2; break; @@ -356,6 +359,17 @@ #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + FT_BASE( void ) + ft_lcd_filter_fir( FT_Bitmap* bitmap, + FT_Render_Mode mode, + FT_LcdFiveTapFilter weights ) + { + FT_UNUSED( bitmap ); + FT_UNUSED( mode ); + FT_UNUSED( weights ); + } + + FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdFilterWeights( FT_Library library, unsigned char *weights ) diff --git a/Source/ThirdParty/FreeType/src/base/ftmac.c b/Source/ThirdParty/FreeType/src/base/ftmac.c index f0edc94ea3..4b92066da3 100644 --- a/Source/ThirdParty/FreeType/src/base/ftmac.c +++ b/Source/ThirdParty/FreeType/src/base/ftmac.c @@ -8,7 +8,7 @@ /* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */ /* classic platforms built by MPW. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -71,6 +71,9 @@ #include FT_INTERNAL_STREAM_H #include "ftbase.h" + +#ifdef FT_MACINTOSH + /* This is for Mac OS X. Without redefinition, OS_INLINE */ /* expands to `static inline' which doesn't survive the */ /* -ansi compilation flag of GCC. */ @@ -118,8 +121,6 @@ #endif -#ifdef FT_MACINTOSH - /* This function is deprecated because FSSpec is deprecated in Mac OS X */ FT_EXPORT_DEF( FT_Error ) FT_GetFile_From_Mac_Name( const char* fontName, @@ -1076,7 +1077,12 @@ #endif } -#endif /* FT_MACINTOSH */ +#else /* !FT_MACINTOSH */ + + /* ANSI C doesn't like empty source files */ + typedef int _ft_mac_dummy; + +#endif /* !FT_MACINTOSH */ /* END */ diff --git a/Source/ThirdParty/FreeType/src/base/ftmm.c b/Source/ThirdParty/FreeType/src/base/ftmm.c index 1b724ace69..2cb56a39be 100644 --- a/Source/ThirdParty/FreeType/src/base/ftmm.c +++ b/Source/ThirdParty/FreeType/src/base/ftmm.c @@ -4,7 +4,7 @@ /* */ /* Multiple Master font support (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,6 +22,7 @@ #include FT_MULTIPLE_MASTERS_H #include FT_INTERNAL_OBJECTS_H #include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H /*************************************************************************/ @@ -62,6 +63,34 @@ } + static FT_Error + ft_face_get_mvar_service( FT_Face face, + FT_Service_MetricsVariations *aservice ) + { + FT_Error error; + + + *aservice = NULL; + + if ( !face ) + return FT_THROW( Invalid_Face_Handle ); + + error = FT_ERR( Invalid_Argument ); + + if ( FT_HAS_MULTIPLE_MASTERS( face ) ) + { + FT_FACE_LOOKUP_SERVICE( face, + *aservice, + METRICS_VARIATIONS ); + + if ( *aservice ) + error = FT_Err_Ok; + } + + return error; + } + + /* documentation is in ftmm.h */ FT_EXPORT_DEF( FT_Error ) @@ -158,8 +187,9 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - FT_Service_MultiMasters service; + FT_Error error; + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; /* check of `face' delayed to `ft_face_get_mm_service' */ @@ -167,12 +197,20 @@ if ( !coords ) return FT_THROW( Invalid_Argument ); - error = ft_face_get_mm_service( face, &service ); + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service->set_var_design ) - error = service->set_var_design( face, num_coords, coords ); + if ( service_mm->set_var_design ) + error = service_mm->set_var_design( face, num_coords, coords ); + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); } /* enforce recomputation of auto-hinting data */ @@ -221,8 +259,9 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - FT_Service_MultiMasters service; + FT_Error error; + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; /* check of `face' delayed to `ft_face_get_mm_service' */ @@ -230,12 +269,20 @@ if ( !coords ) return FT_THROW( Invalid_Argument ); - error = ft_face_get_mm_service( face, &service ); + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_blend ) - error = service->set_mm_blend( face, num_coords, coords ); + if ( service_mm->set_mm_blend ) + error = service_mm->set_mm_blend( face, num_coords, coords ); + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); } /* enforce recomputation of auto-hinting data */ @@ -259,8 +306,9 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - FT_Service_MultiMasters service; + FT_Error error; + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; /* check of `face' delayed to `ft_face_get_mm_service' */ @@ -268,12 +316,20 @@ if ( !coords ) return FT_THROW( Invalid_Argument ); - error = ft_face_get_mm_service( face, &service ); + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_blend ) - error = service->set_mm_blend( face, num_coords, coords ); + if ( service_mm->set_mm_blend ) + error = service_mm->set_mm_blend( face, num_coords, coords ); + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); } /* enforce recomputation of auto-hinting data */ diff --git a/Source/ThirdParty/FreeType/src/base/ftobjs.c b/Source/ThirdParty/FreeType/src/base/ftobjs.c index 4f2a9ecdbe..539116e85c 100644 --- a/Source/ThirdParty/FreeType/src/base/ftobjs.c +++ b/Source/ThirdParty/FreeType/src/base/ftobjs.c @@ -4,7 +4,7 @@ /* */ /* The FreeType private base classes (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -37,6 +37,9 @@ #include FT_SERVICE_KERNING_H #include FT_SERVICE_TRUETYPE_ENGINE_H +#include FT_AUTOHINTER_H +#include FT_CFF_DRIVER_H + #ifdef FT_CONFIG_OPTION_MAC_FONTS #include "ftbase.h" #endif @@ -462,7 +465,8 @@ Exit: - FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); + FT_TRACE4(( "FT_New_GlyphSlot: Return 0x%x\n", error )); + return error; } @@ -698,7 +702,7 @@ /* check the size of the `fpgm' and `prep' tables, too -- */ /* the assumption is that there don't exist real TTFs where */ /* both `fpgm' and `prep' tables are missing */ - if ( ( mode == FT_RENDER_MODE_LIGHT && + if ( ( mode == FT_RENDER_MODE_LIGHT && !FT_DRIVER_HINTS_LIGHTLY( driver ) ) || ( FT_IS_SFNT( face ) && ttface->num_locations && @@ -1185,6 +1189,8 @@ } #endif + face->internal->random_seed = -1; + if ( clazz->init_face ) error = clazz->init_face( *astream, face, @@ -2031,13 +2037,15 @@ { FT_TRACE3(( "Skip rule %d: darwin vfs resource fork" " is already checked and" - " no font is found\n", i )); + " no font is found\n", + i )); continue; } if ( errors[i] ) { - FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); + FT_TRACE3(( "Error 0x%x has occurred in rule %d\n", + errors[i], i )); continue; } @@ -2396,7 +2404,7 @@ if ( bsize->height < 0 || bsize->x_ppem < 0 || bsize->y_ppem < 0 ) { FT_TRACE0(( "FT_Open_Face:" - " Invalid bitmap dimensions for stroke %d," + " Invalid bitmap dimensions for strike %d," " now disabled\n", i )); bsize->width = 0; bsize->height = 0; @@ -2421,6 +2429,12 @@ internal->transform_delta.y = 0; internal->refcount = 1; + + internal->no_stem_darkening = -1; + +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS ); +#endif } if ( aface ) @@ -2440,15 +2454,17 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !error && face_index < 0 ) { - FT_TRACE3(( "FT_Open_Face: The font has %ld faces\n" - " and %ld named instances for face %ld\n", + FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n" + " and %ld named instance%s for face %ld\n", face->num_faces, + face->num_faces == 1 ? "" : "s", face->style_flags >> 16, + ( face->style_flags >> 16 ) == 1 ? "" : "s", -face_index - 1 )); } #endif - FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); + FT_TRACE4(( "FT_Open_Face: Return 0x%x\n", error )); return error; } @@ -2589,6 +2605,8 @@ FT_Size size = NULL; FT_ListNode node = NULL; + FT_Size_Internal internal = NULL; + if ( !face ) return FT_THROW( Invalid_Face_Handle ); @@ -2611,8 +2629,10 @@ size->face = face; - /* for now, do not use any internal fields in size objects */ - size->internal = NULL; + if ( FT_NEW( internal ) ) + goto Exit; + + size->internal = internal; if ( clazz->init_size ) error = clazz->init_size( size ); @@ -3040,6 +3060,10 @@ req->type >= FT_SIZE_REQUEST_TYPE_MAX ) return FT_THROW( Invalid_Argument ); + /* signal the auto-hinter to recompute its size metrics */ + /* (if requested) */ + face->size->internal->autohint_metrics.x_scale = 0; + clazz = face->driver->clazz; if ( clazz->request_size ) @@ -3584,6 +3608,90 @@ } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Face_Properties( FT_Face face, + FT_UInt num_properties, + FT_Parameter* properties ) + { + FT_Error error = FT_Err_Ok; + + + if ( num_properties > 0 && !properties ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + for ( ; num_properties > 0; num_properties-- ) + { + if ( properties->tag == FT_PARAM_TAG_STEM_DARKENING ) + { + if ( properties->data ) + { + if ( *( (FT_Bool*)properties->data ) == TRUE ) + face->internal->no_stem_darkening = FALSE; + else + face->internal->no_stem_darkening = TRUE; + } + else + { + /* use module default */ + face->internal->no_stem_darkening = -1; + } + } + else if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS ) + { +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + if ( properties->data ) + ft_memcpy( face->internal->lcd_weights, + properties->data, + FT_LCD_FILTER_FIVE_TAPS ); + else + { + /* Value NULL indicates `no custom weights, use library */ + /* defaults', signaled by filling the weight field with zeros. */ + ft_memset( face->internal->lcd_weights, + 0, + FT_LCD_FILTER_FIVE_TAPS ); + } +#else + error = FT_THROW( Unimplemented_Feature ); + goto Exit; +#endif + } + else if ( properties->tag == FT_PARAM_TAG_RANDOM_SEED ) + { + if ( properties->data ) + { + face->internal->random_seed = *( (FT_Int32*)properties->data ); + if ( face->internal->random_seed < 0 ) + face->internal->random_seed = 0; + } + else + { + /* use module default */ + face->internal->random_seed = -1; + } + } + else + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( error ) + break; + + properties++; + } + + Exit: + return error; + } + + /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_UInt ) @@ -3609,12 +3717,14 @@ if ( charcode > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); + FT_TRACE1(( "FT_Face_GetCharVariantIndex:" + " too large charcode" )); FT_TRACE1(( " 0x%x is truncated\n", charcode )); } if ( variantSelector > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); + FT_TRACE1(( "FT_Face_GetCharVariantIndex:" + " too large variantSelector" )); FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); } @@ -3650,12 +3760,14 @@ if ( charcode > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); + FT_TRACE1(( "FT_Face_GetCharVariantIsDefault:" + " too large charcode" )); FT_TRACE1(( " 0x%x is truncated\n", charcode )); } if ( variantSelector > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); + FT_TRACE1(( "FT_Face_GetCharVariantIsDefault:" + " too large variantSelector" )); FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); } @@ -3718,7 +3830,7 @@ if ( charcode > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); + FT_TRACE1(( "FT_Face_GetVariantsOfChar: too large charcode" )); FT_TRACE1(( " 0x%x is truncated\n", charcode )); } diff --git a/Source/ThirdParty/FreeType/src/base/ftotval.c b/Source/ThirdParty/FreeType/src/base/ftotval.c index fe54e0228a..5fa098691e 100644 --- a/Source/ThirdParty/FreeType/src/base/ftotval.c +++ b/Source/ThirdParty/FreeType/src/base/ftotval.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for validating OpenType tables (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftoutln.c b/Source/ThirdParty/FreeType/src/base/ftoutln.c index fc28225c6a..464a066dcc 100644 --- a/Source/ThirdParty/FreeType/src/base/ftoutln.c +++ b/Source/ThirdParty/FreeType/src/base/ftoutln.c @@ -4,7 +4,7 @@ /* */ /* FreeType outline management (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -287,7 +287,7 @@ return FT_Err_Ok; Exit: - FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); + FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error )); return error; Invalid_Outline: diff --git a/Source/ThirdParty/FreeType/src/base/ftpatent.c b/Source/ThirdParty/FreeType/src/base/ftpatent.c index 4861be130e..9900f99bfc 100644 --- a/Source/ThirdParty/FreeType/src/base/ftpatent.c +++ b/Source/ThirdParty/FreeType/src/base/ftpatent.c @@ -3,9 +3,9 @@ /* ftpatent.c */ /* */ /* FreeType API for checking patented TrueType bytecode instructions */ -/* (body). Obsolete, retained for backwards compatibility. */ +/* (body). Obsolete, retained for backward compatibility. */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftpfr.c b/Source/ThirdParty/FreeType/src/base/ftpfr.c index 81faa529c3..5cc0b70726 100644 --- a/Source/ThirdParty/FreeType/src/base/ftpfr.c +++ b/Source/ThirdParty/FreeType/src/base/ftpfr.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing PFR-specific data (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftpic.c b/Source/ThirdParty/FreeType/src/base/ftpic.c index 03769dba22..0f84fddc98 100644 --- a/Source/ThirdParty/FreeType/src/base/ftpic.c +++ b/Source/ThirdParty/FreeType/src/base/ftpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services (body). */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftrfork.c b/Source/ThirdParty/FreeType/src/base/ftrfork.c index eac2ddba91..f7b81375dd 100644 --- a/Source/ThirdParty/FreeType/src/base/ftrfork.c +++ b/Source/ThirdParty/FreeType/src/base/ftrfork.c @@ -4,7 +4,7 @@ /* */ /* Embedded resource forks accessor (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Masatake YAMATO and Redhat K.K. */ /* */ /* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */ diff --git a/Source/ThirdParty/FreeType/src/base/ftsnames.c b/Source/ThirdParty/FreeType/src/base/ftsnames.c index e0d5f824de..3609450088 100644 --- a/Source/ThirdParty/FreeType/src/base/ftsnames.c +++ b/Source/ThirdParty/FreeType/src/base/ftsnames.c @@ -7,7 +7,7 @@ /* */ /* This is _not_ used to retrieve glyph names! */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,8 @@ #include <ft2build.h> +#include FT_INTERNAL_DEBUG_H + #include FT_SFNT_NAMES_H #include FT_INTERNAL_TRUETYPE_TYPES_H #include FT_INTERNAL_STREAM_H @@ -54,7 +56,7 @@ if ( idx < (FT_UInt)ttface->num_names ) { - TT_NameEntryRec* entry = ttface->name_table.names + idx; + TT_Name entry = ttface->name_table.names + idx; /* load name on demand */ @@ -88,6 +90,58 @@ } + /* documentation is in ftsnames.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Sfnt_LangTag( FT_Face face, + FT_UInt langID, + FT_SfntLangTag *alangTag ) + { + FT_Error error = FT_ERR( Invalid_Argument ); + + + if ( alangTag && face && FT_IS_SFNT( face ) ) + { + TT_Face ttface = (TT_Face)face; + + + if ( ttface->name_table.format != 1 ) + return FT_THROW( Invalid_Table ); + + if ( langID > 0x8000U && + langID - 0x8000U < ttface->name_table.numLangTagRecords ) + { + TT_LangTag entry = ttface->name_table.langTags + + ( langID - 0x8000U ); + + + /* load name on demand */ + if ( entry->stringLength > 0 && !entry->string ) + { + FT_Memory memory = face->memory; + FT_Stream stream = face->stream; + + + if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || + FT_STREAM_SEEK( entry->stringOffset ) || + FT_STREAM_READ( entry->string, entry->stringLength ) ) + { + FT_FREE( entry->string ); + entry->stringLength = 0; + } + } + + alangTag->string = (FT_Byte*)entry->string; + alangTag->string_len = entry->stringLength; + + error = FT_Err_Ok; + } + } + + return error; + } + + #endif /* TT_CONFIG_OPTION_SFNT_NAMES */ diff --git a/Source/ThirdParty/FreeType/src/base/ftstream.c b/Source/ThirdParty/FreeType/src/base/ftstream.c index bb512a7ccb..a3f8c8b3c9 100644 --- a/Source/ThirdParty/FreeType/src/base/ftstream.c +++ b/Source/ThirdParty/FreeType/src/base/ftstream.c @@ -4,7 +4,7 @@ /* */ /* I/O stream support (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftstroke.c b/Source/ThirdParty/FreeType/src/base/ftstroke.c index 4f3c4937b5..d32de0d62b 100644 --- a/Source/ThirdParty/FreeType/src/base/ftstroke.c +++ b/Source/ThirdParty/FreeType/src/base/ftstroke.c @@ -4,7 +4,7 @@ /* */ /* FreeType path stroker (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftsynth.c b/Source/ThirdParty/FreeType/src/base/ftsynth.c index 4b66a33c3f..66dae6037a 100644 --- a/Source/ThirdParty/FreeType/src/base/ftsynth.c +++ b/Source/ThirdParty/FreeType/src/base/ftsynth.c @@ -4,7 +4,7 @@ /* */ /* FreeType synthesizing code for emboldening and slanting (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -130,7 +130,7 @@ if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN ) { FT_TRACE1(( "FT_GlyphSlot_Embolden:" )); - FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr )); + FT_TRACE1(( "too strong emboldening parameter ystr=%d\n", ystr )); return; } error = FT_GlyphSlot_Own_Bitmap( slot ); diff --git a/Source/ThirdParty/FreeType/src/base/ftsystem.c b/Source/ThirdParty/FreeType/src/base/ftsystem.c index ac1f01c8bc..324f949a49 100644 --- a/Source/ThirdParty/FreeType/src/base/ftsystem.c +++ b/Source/ThirdParty/FreeType/src/base/ftsystem.c @@ -4,7 +4,7 @@ /* */ /* ANSI-specific FreeType low-level system interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/fttrigon.c b/Source/ThirdParty/FreeType/src/base/fttrigon.c index 7b582c8a3d..7a4d17c829 100644 --- a/Source/ThirdParty/FreeType/src/base/fttrigon.c +++ b/Source/ThirdParty/FreeType/src/base/fttrigon.c @@ -4,7 +4,7 @@ /* */ /* FreeType trigonometric functions (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/fttype1.c b/Source/ThirdParty/FreeType/src/base/fttype1.c index 5c0fce8686..4d16a6371a 100644 --- a/Source/ThirdParty/FreeType/src/base/fttype1.c +++ b/Source/ThirdParty/FreeType/src/base/fttype1.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file for PS names support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftutil.c b/Source/ThirdParty/FreeType/src/base/ftutil.c index 36d2dd7210..dccc209f4d 100644 --- a/Source/ThirdParty/FreeType/src/base/ftutil.c +++ b/Source/ThirdParty/FreeType/src/base/ftutil.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file for memory and list management (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftwinfnt.c b/Source/ThirdParty/FreeType/src/base/ftwinfnt.c index 89e9155098..05baa02da6 100644 --- a/Source/ThirdParty/FreeType/src/base/ftwinfnt.c +++ b/Source/ThirdParty/FreeType/src/base/ftwinfnt.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing Windows FNT specific info (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/base/ftxf86.c b/Source/ThirdParty/FreeType/src/base/ftxf86.c deleted file mode 100644 index a4bf767dfa..0000000000 --- a/Source/ThirdParty/FreeType/src/base/ftxf86.c +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftxf86.c */ -/* */ -/* FreeType utility file for X11 support (body). */ -/* */ -/* Copyright 2002, 2003, 2004 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_XFREE86_H -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_XFREE86_NAME_H - - - /* documentation is in ftxf86.h */ - - FT_EXPORT_DEF( const char* ) - FT_Get_X11_Font_Format( FT_Face face ) - { - const char* result = NULL; - - - if ( face ) - FT_FACE_FIND_SERVICE( face, result, XF86_NAME ); - - return result; - } - - -/* END */ diff --git a/Source/ThirdParty/FreeType/src/bdf/bdf.c b/Source/ThirdParty/FreeType/src/bdf/bdf.c index f95fb76225..e54df6649b 100644 --- a/Source/ThirdParty/FreeType/src/bdf/bdf.c +++ b/Source/ThirdParty/FreeType/src/bdf/bdf.c @@ -24,9 +24,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> + #include "bdflib.c" #include "bdfdrivr.c" diff --git a/Source/ThirdParty/FreeType/src/bzip2/ftbzip2.c b/Source/ThirdParty/FreeType/src/bzip2/ftbzip2.c index 4d0b388d6a..7fc71e7079 100644 --- a/Source/ThirdParty/FreeType/src/bzip2/ftbzip2.c +++ b/Source/ThirdParty/FreeType/src/bzip2/ftbzip2.c @@ -8,7 +8,7 @@ /* parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2017 by */ /* Joel Klinghed. */ /* */ /* based on `src/gzip/ftgzip.c' */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcache.c b/Source/ThirdParty/FreeType/src/cache/ftcache.c index 50941df4c4..8226188314 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcache.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcache.c @@ -4,7 +4,7 @@ /* */ /* The FreeType Caching sub-system (body only). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,15 +17,16 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "ftcmru.c" -#include "ftcmanag.c" + +#include "ftcbasic.c" #include "ftccache.c" #include "ftccmap.c" #include "ftcglyph.c" #include "ftcimage.c" +#include "ftcmanag.c" +#include "ftcmru.c" #include "ftcsbits.c" -#include "ftcbasic.c" + /* END */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcbasic.c b/Source/ThirdParty/FreeType/src/cache/ftcbasic.c index fc8905c950..289bd5c430 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcbasic.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcbasic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType basic cache interface (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftccache.c b/Source/ThirdParty/FreeType/src/cache/ftccache.c index de20255335..37dc3abb1d 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftccache.c +++ b/Source/ThirdParty/FreeType/src/cache/ftccache.c @@ -4,7 +4,7 @@ /* */ /* The FreeType internal cache interface (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftccache.h b/Source/ThirdParty/FreeType/src/cache/ftccache.h index ab4ea51242..d3c11ce082 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftccache.h +++ b/Source/ThirdParty/FreeType/src/cache/ftccache.h @@ -4,7 +4,7 @@ /* */ /* FreeType internal cache interface (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftccback.h b/Source/ThirdParty/FreeType/src/cache/ftccback.h index 279e94d923..2681e8c022 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftccback.h +++ b/Source/ThirdParty/FreeType/src/cache/ftccback.h @@ -4,7 +4,7 @@ /* */ /* Callback functions of the caching sub-system (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftccmap.c b/Source/ThirdParty/FreeType/src/cache/ftccmap.c index f0a85f9c5d..2fa84979c8 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftccmap.c +++ b/Source/ThirdParty/FreeType/src/cache/ftccmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType CharMap cache (body) */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcerror.h b/Source/ThirdParty/FreeType/src/cache/ftcerror.h index 1fd7357a8b..84fe52f546 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcerror.h +++ b/Source/ThirdParty/FreeType/src/cache/ftcerror.h @@ -4,7 +4,7 @@ /* */ /* Caching sub-system error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcglyph.c b/Source/ThirdParty/FreeType/src/cache/ftcglyph.c index c4046812dd..d2468f2f43 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcglyph.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcglyph.c @@ -4,7 +4,7 @@ /* */ /* FreeType Glyph Image (FT_Glyph) cache (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcglyph.h b/Source/ThirdParty/FreeType/src/cache/ftcglyph.h index dc7be06f03..cab58ed311 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcglyph.h +++ b/Source/ThirdParty/FreeType/src/cache/ftcglyph.h @@ -4,7 +4,7 @@ /* */ /* FreeType abstract glyph cache (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcimage.c b/Source/ThirdParty/FreeType/src/cache/ftcimage.c index 74040aa745..359f818cce 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcimage.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcimage.c @@ -4,7 +4,7 @@ /* */ /* FreeType Image cache (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcimage.h b/Source/ThirdParty/FreeType/src/cache/ftcimage.h index 25aa43b97e..14049af9d2 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcimage.h +++ b/Source/ThirdParty/FreeType/src/cache/ftcimage.h @@ -4,7 +4,7 @@ /* */ /* FreeType Generic Image cache (specification) */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcmanag.c b/Source/ThirdParty/FreeType/src/cache/ftcmanag.c index 9a25b9772b..edec2b6b5b 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcmanag.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcmanag.c @@ -4,7 +4,7 @@ /* */ /* FreeType Cache Manager (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcmanag.h b/Source/ThirdParty/FreeType/src/cache/ftcmanag.h index f2c434a135..556842e131 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcmanag.h +++ b/Source/ThirdParty/FreeType/src/cache/ftcmanag.h @@ -4,7 +4,7 @@ /* */ /* FreeType Cache Manager (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcmru.c b/Source/ThirdParty/FreeType/src/cache/ftcmru.c index 7c460b928a..e293269f2f 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcmru.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcmru.c @@ -4,7 +4,7 @@ /* */ /* FreeType MRU support (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcmru.h b/Source/ThirdParty/FreeType/src/cache/ftcmru.h index 27ad55aa05..c4c330d558 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcmru.h +++ b/Source/ThirdParty/FreeType/src/cache/ftcmru.h @@ -4,7 +4,7 @@ /* */ /* Simple MRU list-cache (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcsbits.c b/Source/ThirdParty/FreeType/src/cache/ftcsbits.c index 78cd8de82b..2f9336decd 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcsbits.c +++ b/Source/ThirdParty/FreeType/src/cache/ftcsbits.c @@ -4,7 +4,7 @@ /* */ /* FreeType sbits manager (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cache/ftcsbits.h b/Source/ThirdParty/FreeType/src/cache/ftcsbits.h index a0600ede09..1e15ce9764 100644 --- a/Source/ThirdParty/FreeType/src/cache/ftcsbits.h +++ b/Source/ThirdParty/FreeType/src/cache/ftcsbits.h @@ -4,7 +4,7 @@ /* */ /* A small-bitmap cache (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cf2error.h b/Source/ThirdParty/FreeType/src/cff/cf2error.h index 512edd1d21..d2c770d297 100644 --- a/Source/ThirdParty/FreeType/src/cff/cf2error.h +++ b/Source/ThirdParty/FreeType/src/cff/cf2error.h @@ -66,7 +66,7 @@ FT_BEGIN_HEADER * model our error mechanism on a Java-like exception mechanism. * When we assign an error code we are thus `throwing' an error. * - * The perservation of an error code is done by coding convention. + * The preservation of an error code is done by coding convention. * Upon a function call if the error code is anything other than * `FT_Err_Ok', which is guaranteed to be zero, we * will return without altering that error. This will allow the diff --git a/Source/ThirdParty/FreeType/src/cff/cf2ft.c b/Source/ThirdParty/FreeType/src/cff/cf2ft.c index c0d067e94e..eb8472f119 100644 --- a/Source/ThirdParty/FreeType/src/cff/cf2ft.c +++ b/Source/ThirdParty/FreeType/src/cff/cf2ft.c @@ -340,6 +340,11 @@ CFF_Builder* builder = &decoder->builder; CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); + FT_Bool no_stem_darkening_driver = + driver->no_stem_darkening; + FT_Char no_stem_darkening_font = + builder->face->root.internal->no_stem_darkening; + /* local error */ FT_Error error2 = FT_Err_Ok; CF2_BufferRec buf; @@ -368,12 +373,14 @@ &scaled ); /* copy isCFF2 boolean from TT_Face to CF2_Font */ - font->isCFF2 = builder->face->isCFF2; + font->isCFF2 = builder->face->is_cff2; font->renderingFlags = 0; if ( hinted ) font->renderingFlags |= CF2_FlagsHinted; - if ( scaled && !driver->no_stem_darkening ) + if ( scaled && ( !no_stem_darkening_font || + ( no_stem_darkening_font < 0 && + !no_stem_darkening_driver ) ) ) font->renderingFlags |= CF2_FlagsDarkened; font->darkenParams[0] = driver->darken_params[0]; @@ -450,7 +457,7 @@ FT_ASSERT( decoder && decoder->builder.face ); FT_ASSERT( vec && len ); - return cff_get_var_blend( decoder->builder.face, len, vec, NULL ); + return cff_get_var_blend( decoder->builder.face, len, NULL, vec, NULL ); } #endif diff --git a/Source/ThirdParty/FreeType/src/cff/cf2intrp.c b/Source/ThirdParty/FreeType/src/cff/cf2intrp.c index 6bf298a4d6..40bd9059a1 100644 --- a/Source/ThirdParty/FreeType/src/cff/cf2intrp.c +++ b/Source/ThirdParty/FreeType/src/cff/cf2intrp.c @@ -60,12 +60,6 @@ #define FT_COMPONENT trace_cf2interp - /* some operators are not implemented yet */ -#define CF2_FIXME FT_TRACE4(( "cf2_interpT2CharString:" \ - " operator not implemented yet\n" )) - - - FT_LOCAL_DEF( void ) cf2_hintmask_init( CF2_HintMask hintmask, FT_Error* error ) @@ -339,14 +333,14 @@ FT_Bool doConditionalLastRead ) { CF2_Fixed vals[14]; - CF2_UInt index; + CF2_UInt idx; FT_Bool isHFlex; CF2_Int top, i, j; vals[0] = *curX; vals[1] = *curY; - index = 0; + idx = 0; isHFlex = FT_BOOL( readFromStack[9] == FALSE ); top = isHFlex ? 9 : 10; @@ -354,7 +348,7 @@ { vals[i + 2] = vals[i]; if ( readFromStack[i] ) - vals[i + 2] += cf2_stack_getReal( opStack, index++ ); + vals[i + 2] += cf2_stack_getReal( opStack, idx++ ); } if ( isHFlex ) @@ -364,7 +358,7 @@ { FT_Bool lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) > cf2_fixedAbs( vals[11] - *curY ) ); - CF2_Fixed lastVal = cf2_stack_getReal( opStack, index ); + CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx ); if ( lastIsX ) @@ -381,12 +375,12 @@ else { if ( readFromStack[10] ) - vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ ); + vals[12] = vals[10] + cf2_stack_getReal( opStack, idx++ ); else vals[12] = *curX; if ( readFromStack[11] ) - vals[13] = vals[11] + cf2_stack_getReal( opStack, index ); + vals[13] = vals[11] + cf2_stack_getReal( opStack, idx ); else vals[13] = *curY; } @@ -781,16 +775,16 @@ case cf2_cmdRLINETO: { - CF2_UInt index; + CF2_UInt idx; CF2_UInt count = cf2_stack_count( opStack ); FT_TRACE4(( " rlineto\n" )); - for ( index = 0; index < count; index += 2 ) + for ( idx = 0; idx < count; idx += 2 ) { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); + curX += cf2_stack_getReal( opStack, idx + 0 ); + curY += cf2_stack_getReal( opStack, idx + 1 ); cf2_glyphpath_lineTo( &glyphPath, curX, curY ); } @@ -802,7 +796,7 @@ case cf2_cmdHLINETO: case cf2_cmdVLINETO: { - CF2_UInt index; + CF2_UInt idx; CF2_UInt count = cf2_stack_count( opStack ); FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO ); @@ -810,9 +804,9 @@ FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); - for ( index = 0; index < count; index++ ) + for ( idx = 0; idx < count; idx++ ) { - CF2_Fixed v = cf2_stack_getReal( opStack, index ); + CF2_Fixed v = cf2_stack_getReal( opStack, idx ); if ( isX ) @@ -833,33 +827,33 @@ case cf2_cmdRRCURVETO: { CF2_UInt count = cf2_stack_count( opStack ); - CF2_UInt index = 0; + CF2_UInt idx = 0; FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n" : " rrcurveto\n" )); - while ( index + 6 <= count ) + while ( idx + 6 <= count ) { - CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY; - CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1; - CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1; - CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2; + CF2_Fixed x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX; + CF2_Fixed y1 = cf2_stack_getReal( opStack, idx + 1 ) + curY; + CF2_Fixed x2 = cf2_stack_getReal( opStack, idx + 2 ) + x1; + CF2_Fixed y2 = cf2_stack_getReal( opStack, idx + 3 ) + y1; + CF2_Fixed x3 = cf2_stack_getReal( opStack, idx + 4 ) + x2; + CF2_Fixed y3 = cf2_stack_getReal( opStack, idx + 5 ) + y2; cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - curX = x3; - curY = y3; - index += 6; + curX = x3; + curY = y3; + idx += 6; } if ( op1 == cf2_cmdRCURVELINE ) { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); + curX += cf2_stack_getReal( opStack, idx + 0 ); + curY += cf2_stack_getReal( opStack, idx + 1 ); cf2_glyphpath_lineTo( &glyphPath, curX, curY ); } @@ -1268,10 +1262,23 @@ continue; /* do not clear the stack */ case cf2_escRANDOM: /* in spec */ - FT_TRACE4(( " random\n" )); + { + CF2_F16Dot16 r; - CF2_FIXME; - break; + + FT_TRACE4(( " random\n" )); + + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + r = (CF2_F16Dot16) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); + + cf2_stack_pushFixed( opStack, r ); + } + continue; /* do not clear the stack */ case cf2_escMUL: { @@ -1593,35 +1600,35 @@ case cf2_cmdRLINECURVE: { CF2_UInt count = cf2_stack_count( opStack ); - CF2_UInt index = 0; + CF2_UInt idx = 0; FT_TRACE4(( " rlinecurve\n" )); - while ( index + 6 < count ) + while ( idx + 6 < count ) { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); + curX += cf2_stack_getReal( opStack, idx + 0 ); + curY += cf2_stack_getReal( opStack, idx + 1 ); cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - index += 2; + idx += 2; } - while ( index < count ) + while ( idx < count ) { - CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY; - CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1; - CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1; - CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2; + CF2_Fixed x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX; + CF2_Fixed y1 = cf2_stack_getReal( opStack, idx + 1 ) + curY; + CF2_Fixed x2 = cf2_stack_getReal( opStack, idx + 2 ) + x1; + CF2_Fixed y2 = cf2_stack_getReal( opStack, idx + 3 ) + y1; + CF2_Fixed x3 = cf2_stack_getReal( opStack, idx + 4 ) + x2; + CF2_Fixed y3 = cf2_stack_getReal( opStack, idx + 5 ) + y2; cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - curX = x3; - curY = y3; - index += 6; + curX = x3; + curY = y3; + idx += 6; } cf2_stack_clear( opStack ); @@ -1631,42 +1638,42 @@ case cf2_cmdVVCURVETO: { CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; + CF2_UInt idx = 0; /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ /* we enforce it by clearing the second bit */ /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; + count = count1 & ~2U; + idx += count1 - count; FT_TRACE4(( " vvcurveto\n" )); - while ( index < count ) + while ( idx < count ) { CF2_Fixed x1, y1, x2, y2, x3, y3; - if ( ( count - index ) & 1 ) + if ( ( count - idx ) & 1 ) { - x1 = cf2_stack_getReal( opStack, index ) + curX; + x1 = cf2_stack_getReal( opStack, idx ) + curX; - index++; + idx++; } else x1 = curX; - y1 = cf2_stack_getReal( opStack, index + 0 ) + curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; + y1 = cf2_stack_getReal( opStack, idx + 0 ) + curY; + x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1; + y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1; x3 = x2; - y3 = cf2_stack_getReal( opStack, index + 3 ) + y2; + y3 = cf2_stack_getReal( opStack, idx + 3 ) + y2; cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - curX = x3; - curY = y3; - index += 4; + curX = x3; + curY = y3; + idx += 4; } cf2_stack_clear( opStack ); @@ -1676,42 +1683,42 @@ case cf2_cmdHHCURVETO: { CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; + CF2_UInt idx = 0; /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ /* we enforce it by clearing the second bit */ /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; + count = count1 & ~2U; + idx += count1 - count; FT_TRACE4(( " hhcurveto\n" )); - while ( index < count ) + while ( idx < count ) { CF2_Fixed x1, y1, x2, y2, x3, y3; - if ( ( count - index ) & 1 ) + if ( ( count - idx ) & 1 ) { - y1 = cf2_stack_getReal( opStack, index ) + curY; + y1 = cf2_stack_getReal( opStack, idx ) + curY; - index++; + idx++; } else y1 = curY; - x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = cf2_stack_getReal( opStack, index + 3 ) + x2; + x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX; + x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1; + y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1; + x3 = cf2_stack_getReal( opStack, idx + 3 ) + x2; y3 = y2; cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - curX = x3; - curY = y3; - index += 4; + curX = x3; + curY = y3; + idx += 4; } cf2_stack_clear( opStack ); @@ -1722,7 +1729,7 @@ case cf2_cmdHVCURVETO: { CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; + CF2_UInt idx = 0; FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); @@ -1731,29 +1738,29 @@ /* 8n+4, or 8n+5, we enforce it by clearing the */ /* second bit */ /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; + count = count1 & ~2U; + idx += count1 - count; FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" )); - while ( index < count ) + while ( idx < count ) { CF2_Fixed x1, x2, x3, y1, y2, y3; if ( alternate ) { - x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; + x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX; y1 = curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - y3 = cf2_stack_getReal( opStack, index + 3 ) + y2; + x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1; + y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1; + y3 = cf2_stack_getReal( opStack, idx + 3 ) + y2; - if ( count - index == 5 ) + if ( count - idx == 5 ) { - x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; + x3 = cf2_stack_getReal( opStack, idx + 4 ) + x2; - index++; + idx++; } else x3 = x2; @@ -1763,16 +1770,16 @@ else { x1 = curX; - y1 = cf2_stack_getReal( opStack, index + 0 ) + curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = cf2_stack_getReal( opStack, index + 3 ) + x2; + y1 = cf2_stack_getReal( opStack, idx + 0 ) + curY; + x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1; + y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1; + x3 = cf2_stack_getReal( opStack, idx + 3 ) + x2; - if ( count - index == 5 ) + if ( count - idx == 5 ) { - y3 = cf2_stack_getReal( opStack, index + 4 ) + y2; + y3 = cf2_stack_getReal( opStack, idx + 4 ) + y2; - index++; + idx++; } else y3 = y2; @@ -1782,9 +1789,9 @@ cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - curX = x3; - curY = y3; - index += 4; + curX = x3; + curY = y3; + idx += 4; } cf2_stack_clear( opStack ); diff --git a/Source/ThirdParty/FreeType/src/cff/cff.c b/Source/ThirdParty/FreeType/src/cff/cff.c index 86ca1be040..397f6dfafe 100644 --- a/Source/ThirdParty/FreeType/src/cff/cff.c +++ b/Source/ThirdParty/FreeType/src/cff/cff.c @@ -4,7 +4,7 @@ /* */ /* FreeType OpenType driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,16 +17,15 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "cffpic.c" +#include "cffcmap.c" #include "cffdrivr.c" +#include "cffgload.c" #include "cffparse.c" +#include "cffpic.c" #include "cffload.c" #include "cffobjs.c" -#include "cffgload.c" -#include "cffcmap.c" #include "cf2arrst.c" #include "cf2blues.c" @@ -38,4 +37,5 @@ #include "cf2read.c" #include "cf2stack.c" + /* END */ diff --git a/Source/ThirdParty/FreeType/src/cff/cffcmap.c b/Source/ThirdParty/FreeType/src/cff/cffcmap.c index 695ba69d94..4adce7a54d 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffcmap.c +++ b/Source/ThirdParty/FreeType/src/cff/cffcmap.c @@ -4,7 +4,7 @@ /* */ /* CFF character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cffcmap.h b/Source/ThirdParty/FreeType/src/cff/cffcmap.h index 23795d5090..7792e04248 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffcmap.h +++ b/Source/ThirdParty/FreeType/src/cff/cffcmap.h @@ -4,7 +4,7 @@ /* */ /* CFF character mapping table (cmap) support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cffdrivr.c b/Source/ThirdParty/FreeType/src/cff/cffdrivr.c index 31825286e2..38bfc2ca3d 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffdrivr.c +++ b/Source/ThirdParty/FreeType/src/cff/cffdrivr.c @@ -4,7 +4,7 @@ /* */ /* OpenType font driver implementation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -34,6 +34,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H #endif #include "cfferrs.h" @@ -832,6 +833,7 @@ { FT_UInt* hinting_engine = (FT_UInt*)value; + if ( *hinting_engine == FT_CFF_HINTING_ADOBE #ifdef CFF_CONFIG_OPTION_OLD_ENGINE || *hinting_engine == FT_CFF_HINTING_FREETYPE @@ -853,12 +855,10 @@ long nsd = ft_strtol( s, NULL, 10 ); - if ( nsd == 0 ) - driver->no_stem_darkening = 0; - else if ( nsd == 1 ) - driver->no_stem_darkening = 1; + if ( !nsd ) + driver->no_stem_darkening = FALSE; else - return FT_THROW( Invalid_Argument ); + driver->no_stem_darkening = TRUE; } else #endif @@ -871,6 +871,30 @@ return error; } + else if ( !ft_strcmp( property_name, "random-seed" ) ) + { + FT_Int32 random_seed; + + +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + + + random_seed = (FT_Int32)ft_strtol( s, NULL, 10 ); + } + else +#endif + random_seed = *(FT_Int32*)value; + + if ( random_seed < 0 ) + random_seed = 0; + + driver->random_seed = random_seed; + + return error; + } FT_TRACE0(( "cff_property_set: missing property `%s'\n", property_name )); @@ -1018,6 +1042,49 @@ (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ (FT_Done_Blend_Func) cff_done_blend /* done_blend */ ) + + + /* + * METRICS VARIATIONS SERVICE + * + */ + + static FT_Error + cff_hadvance_adjust( CFF_Face face, + FT_UInt gindex, + FT_Int *avalue ) + { + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + + + return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); + } + + + static void + cff_metrics_adjust( CFF_Face face ) + { + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + + + var->metrics_adjust( FT_FACE( face ) ); + } + + + FT_DEFINE_SERVICE_METRICSVARIATIONSREC( + cff_service_metrics_variations, + + (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ + (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ + (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + + (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ + (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ + (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ + (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + + (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ + ) #endif @@ -1035,11 +1102,12 @@ #if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \ defined TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC8( + FT_DEFINE_SERVICEDESCREC9( cff_services, FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET, + FT_SERVICE_ID_METRICS_VARIATIONS, &CFF_SERVICE_METRICS_VAR_GET, FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET, FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET, @@ -1060,11 +1128,12 @@ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET ) #elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC7( + FT_DEFINE_SERVICEDESCREC8( cff_services, FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET, + FT_SERVICE_ID_METRICS_VARIATIONS, &CFF_SERVICE_METRICS_VAR_GET, FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET, FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, diff --git a/Source/ThirdParty/FreeType/src/cff/cffdrivr.h b/Source/ThirdParty/FreeType/src/cff/cffdrivr.h index d7b0598374..05381e66db 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffdrivr.h +++ b/Source/ThirdParty/FreeType/src/cff/cffdrivr.h @@ -4,7 +4,7 @@ /* */ /* High-level OpenType driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cfferrs.h b/Source/ThirdParty/FreeType/src/cff/cfferrs.h index e7fc6eb71c..40808c1051 100644 --- a/Source/ThirdParty/FreeType/src/cff/cfferrs.h +++ b/Source/ThirdParty/FreeType/src/cff/cfferrs.h @@ -4,7 +4,7 @@ /* */ /* CFF error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cffgload.c b/Source/ThirdParty/FreeType/src/cff/cffgload.c index d8084f865b..940804850e 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffgload.c +++ b/Source/ThirdParty/FreeType/src/cff/cffgload.c @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -278,11 +278,15 @@ if ( hinting && size ) { - CFF_Internal internal = (CFF_Internal)size->root.internal; + FT_Size ftsize = FT_SIZE( size ); + CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data; - builder->hints_globals = (void *)internal->topfont; - builder->hints_funcs = glyph->root.internal->glyph_hints; + if ( internal ) + { + builder->hints_globals = (void *)internal->topfont; + builder->hints_funcs = glyph->root.internal->glyph_hints; + } } } @@ -440,7 +444,8 @@ if ( builder->hints_funcs && size ) { - CFF_Internal internal = (CFF_Internal)size->root.internal; + FT_Size ftsize = FT_SIZE( size ); + CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data; /* for CFFs without subfonts, this value has already been set */ @@ -457,7 +462,7 @@ decoder->glyph_width = sub->private_dict.default_width; decoder->nominal_width = sub->private_dict.nominal_width; - decoder->current_subfont = sub; /* for Adobe's CFF handler */ + decoder->current_subfont = sub; Exit: return error; @@ -913,7 +918,6 @@ FT_Byte* limit; CFF_Builder* builder = &decoder->builder; FT_Pos x, y; - FT_Fixed seed; FT_Fixed* stack; FT_Int charstring_type = decoder->cff->top_font.font_dict.charstring_type; @@ -929,15 +933,6 @@ decoder->num_hints = 0; decoder->read_width = 1; - /* compute random seed from stack address of parameter */ - seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^ - (FT_Offset)(char*)&decoder ^ - (FT_Offset)(char*)&charstring_base ) & - FT_ULONG_MAX ); - seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; - if ( seed == 0 ) - seed = 0x7384; - /* initialize the decoder */ decoder->top = decoder->stack; decoder->zone = decoder->zones; @@ -2104,22 +2099,16 @@ break; case cff_op_random: - { - FT_Fixed Rand; - + FT_TRACE4(( " random\n" )); - FT_TRACE4(( " rand\n" )); - - Rand = seed; - if ( Rand >= 0x8000L ) - Rand++; + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + args[0] = (FT_Fixed) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + args++; - args[0] = Rand; - seed = FT_MulFix( seed, 0x10000L - seed ); - if ( seed == 0 ) - seed += 0x2873; - args++; - } + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); break; case cff_op_mul: diff --git a/Source/ThirdParty/FreeType/src/cff/cffgload.h b/Source/ThirdParty/FreeType/src/cff/cffgload.h index b875fbed90..0fa93b4398 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffgload.h +++ b/Source/ThirdParty/FreeType/src/cff/cffgload.h @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cffload.c b/Source/ThirdParty/FreeType/src/cff/cffload.c index c1e6b14dbf..3beaeb1c8e 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffload.c +++ b/Source/ThirdParty/FreeType/src/cff/cffload.c @@ -4,7 +4,7 @@ /* */ /* OpenType and CFF data/program tables loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -1113,7 +1113,7 @@ /* convert 2.14 to Fixed */ - #define FT_fdot14ToFixed( x ) ( ( (FT_Fixed)( (FT_Int16)(x) ) ) << 2 ) + #define FT_fdot14ToFixed( x ) ( (FT_Fixed)( (FT_ULong)(x) << 2 ) ) static FT_Error @@ -1307,6 +1307,10 @@ size = 5 * numBlends; /* add 5 bytes per entry */ if ( subFont->blend_used + size > subFont->blend_alloc ) { + FT_Byte* blend_stack_old = subFont->blend_stack; + FT_Byte* blend_top_old = subFont->blend_top; + + /* increase or allocate `blend_stack' and reset `blend_top'; */ /* prepare to append `numBlends' values to the buffer */ if ( FT_REALLOC( subFont->blend_stack, @@ -1316,6 +1320,22 @@ subFont->blend_top = subFont->blend_stack + subFont->blend_used; subFont->blend_alloc += size; + + /* iterate over the parser stack and adjust pointers */ + /* if the reallocated buffer has a different address */ + if ( blend_stack_old && + subFont->blend_stack != blend_stack_old ) + { + FT_PtrDist offset = subFont->blend_stack - blend_stack_old; + FT_Byte** p; + + + for ( p = parser->stack; p < parser->top; p++ ) + { + if ( *p >= blend_stack_old && *p < blend_top_old ) + *p += offset; + } + } } subFont->blend_used += size; @@ -1329,24 +1349,25 @@ /* convert inputs to 16.16 fixed point */ - sum = cff_parse_num( parser, &parser->stack[i + base] ) << 16; + sum = cff_parse_num( parser, &parser->stack[i + base] ) * 65536; for ( j = 1; j < blend->lenBV; j++ ) sum += FT_MulFix( *weight++, cff_parse_num( parser, - &parser->stack[delta++] ) << 16 ); + &parser->stack[delta++] ) * 65536 ); /* point parser stack to new value on blend_stack */ parser->stack[i + base] = subFont->blend_top; - /* Push blended result as Type 2 5-byte fixed point number (except */ - /* that host byte order is used). This will not conflict with */ - /* actual DICTs because 255 is a reserved opcode in both CFF and */ - /* CFF2 DICTs. See `cff_parse_num' for decode of this, which rounds */ - /* to an integer. */ - *subFont->blend_top++ = 255; - *((FT_UInt32*)subFont->blend_top) = (FT_UInt32)sum; /* write 4 bytes */ - subFont->blend_top += 4; + /* Push blended result as Type 2 5-byte fixed point number. This */ + /* will not conflict with actual DICTs because 255 is a reserved */ + /* opcode in both CFF and CFF2 DICTs. See `cff_parse_num' for */ + /* decode of this, which rounds to an integer. */ + *subFont->blend_top++ = 255; + *subFont->blend_top++ = ( (FT_UInt32)sum & 0xFF000000U ) >> 24; + *subFont->blend_top++ = ( (FT_UInt32)sum & 0x00FF0000U ) >> 16; + *subFont->blend_top++ = ( (FT_UInt32)sum & 0x0000FF00U ) >> 8; + *subFont->blend_top++ = (FT_UInt32)sum & 0x000000FFU; } /* leave only numBlends results on parser stack */ @@ -1442,10 +1463,15 @@ /* Note: `lenNDV' could be zero. */ /* In that case, build default blend vector (1,0,0...). */ - /* In the normal case, initialize each component to 1 */ - /* before inner loop. */ - if ( lenNDV != 0 ) - blend->BV[master] = FT_FIXED_ONE; /* default */ + if ( !lenNDV ) + { + blend->BV[master] = 0; + continue; + } + + /* In the normal case, initialize each component to 1 */ + /* before inner loop. */ + blend->BV[master] = FT_FIXED_ONE; /* default */ /* inner loop steps through axes in this region */ for ( j = 0; j < lenNDV; j++ ) @@ -1508,12 +1534,12 @@ lenNDV * sizeof ( *NDV ) ) ) goto Exit; - blend->lenNDV = lenNDV; FT_MEM_COPY( blend->lastNDV, NDV, lenNDV * sizeof ( *NDV ) ); } + blend->lenNDV = lenNDV; blend->builtBV = TRUE; Exit: @@ -1551,12 +1577,17 @@ cff_get_var_blend( CFF_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - return mm->get_var_blend( FT_FACE( face ), num_coords, coords, mm_var ); + return mm->get_var_blend( FT_FACE( face ), + num_coords, + coords, + normalizedcoords, + mm_var ); } @@ -1864,7 +1895,8 @@ subfont->lenNDV = lenNDV; subfont->NDV = NDV; - stackSize = font->cff2 ? font->top_font.font_dict.maxstack + /* add 1 for the operator */ + stackSize = font->cff2 ? font->top_font.font_dict.maxstack + 1 : CFF_MAX_STACK_DEPTH + 1; if ( cff_parser_init( &parser, @@ -1892,6 +1924,13 @@ /* ensure that `num_blue_values' is even */ priv->num_blue_values &= ~1; + /* sanitize `initialRandomSeed' to be a positive value, if necessary; */ + /* this is not mandated by the specification but by our implementation */ + if ( priv->initial_random_seed < 0 ) + priv->initial_random_seed = -priv->initial_random_seed; + else if ( priv->initial_random_seed == 0 ) + priv->initial_random_seed = 987654321; + Exit: /* clean up */ cff_blend_clear( subfont ); /* clear blend stack */ @@ -1903,6 +1942,18 @@ } + FT_LOCAL_DEF( FT_UInt32 ) + cff_random( FT_UInt32 r ) + { + /* a 32bit version of the `xorshift' algorithm */ + r ^= r << 13; + r ^= r >> 17; + r ^= r << 5; + + return r; + } + + /* There are 3 ways to call this function, distinguished by code. */ /* */ /* . CFF_CODE_TOPDICT for either a CFF Top DICT or a CFF Font DICT */ @@ -1916,7 +1967,8 @@ FT_Stream stream, FT_ULong base_offset, FT_UInt code, - CFF_Font font ) + CFF_Font font, + CFF_Face face ) { FT_Error error; CFF_ParserRec parser; @@ -2013,6 +2065,55 @@ if ( error ) goto Exit; + if ( !cff2 ) + { + /* + * Initialize the random number generator. + * + * . If we have a face-specific seed, use it. + * If non-zero, update it to a positive value. + * + * . Otherwise, use the seed from the CFF driver. + * If non-zero, update it to a positive value. + * + * . If the random value is zero, use the seed given by the subfont's + * `initialRandomSeed' value. + * + */ + if ( face->root.internal->random_seed == -1 ) + { + CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); + + + subfont->random = (FT_UInt32)driver->random_seed; + if ( driver->random_seed ) + { + do + { + driver->random_seed = + (FT_Int32)cff_random( (FT_UInt32)driver->random_seed ); + + } while ( driver->random_seed < 0 ); + } + } + else + { + subfont->random = (FT_UInt32)face->root.internal->random_seed; + if ( face->root.internal->random_seed ) + { + do + { + face->root.internal->random_seed = + (FT_Int32)cff_random( (FT_UInt32)face->root.internal->random_seed ); + + } while ( face->root.internal->random_seed < 0 ); + } + } + + if ( !subfont->random ) + subfont->random = (FT_UInt32)priv->initial_random_seed; + } + /* read the local subrs, if any */ if ( priv->local_subrs_offset ) { @@ -2058,6 +2159,7 @@ FT_Stream stream, FT_Int face_index, CFF_Font font, + CFF_Face face, FT_Bool pure_cff, FT_Bool cff2 ) { @@ -2178,6 +2280,18 @@ goto Exit; } + /* if we have an empty font name, */ + /* it must be the only font in the CFF */ + if ( font->name_index.count > 1 && + font->name_index.data_size < font->name_index.count ) + { + /* for pure CFFs, we still haven't checked enough bytes */ + /* to be sure that it is a CFF at all */ + error = pure_cff ? FT_THROW( Unknown_File_Format ) + : FT_THROW( Invalid_File_Format ); + goto Exit; + } + if ( FT_SET_ERROR( cff_index_init( &font->font_dict_index, stream, 0, cff2 ) ) || FT_SET_ERROR( cff_index_init( &string_index, @@ -2189,6 +2303,15 @@ &font->string_pool, &font->string_pool_size ) ) ) goto Exit; + + /* there must be a Top DICT index entry for each name index entry */ + if ( font->name_index.count > font->font_dict_index.count ) + { + FT_ERROR(( "cff_font_load:" + " not enough entries in Top DICT index\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } } font->num_strings = string_index.count; @@ -2236,7 +2359,8 @@ stream, base_offset, cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT, - font ); + font, + face ); if ( error ) goto Exit; @@ -2303,7 +2427,8 @@ base_offset, cff2 ? CFF2_CODE_FONTDICT : CFF_CODE_TOPDICT, - font ); + font, + face ); if ( error ) goto Fail_CID; } diff --git a/Source/ThirdParty/FreeType/src/cff/cffload.h b/Source/ThirdParty/FreeType/src/cff/cffload.h index dc3a2c5236..c745e8127b 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffload.h +++ b/Source/ThirdParty/FreeType/src/cff/cffload.h @@ -4,7 +4,7 @@ /* */ /* OpenType & CFF data/program tables loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -61,11 +61,15 @@ FT_BEGIN_HEADER FT_UInt cid ); + FT_LOCAL( FT_UInt32 ) + cff_random( FT_UInt32 r ); + FT_LOCAL( FT_Error ) cff_font_load( FT_Library library, FT_Stream stream, FT_Int face_index, CFF_Font font, + CFF_Face face, FT_Bool pure_cff, FT_Bool cff2 ); @@ -108,6 +112,7 @@ FT_BEGIN_HEADER cff_get_var_blend( CFF_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) diff --git a/Source/ThirdParty/FreeType/src/cff/cffobjs.c b/Source/ThirdParty/FreeType/src/cff/cffobjs.c index 926effc523..61613933ff 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffobjs.c +++ b/Source/ThirdParty/FreeType/src/cff/cffobjs.c @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,6 +27,11 @@ #include FT_INTERNAL_SFNT_H #include FT_CFF_DRIVER_H +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#endif + #include "cffobjs.h" #include "cffload.h" #include "cffcmap.h" @@ -49,9 +54,6 @@ /* */ /* SIZE FUNCTIONS */ /* */ - /* Note that we store the global hints in the size's `internal' root */ - /* field. */ - /* */ /*************************************************************************/ @@ -75,10 +77,11 @@ FT_LOCAL_DEF( void ) cff_size_done( FT_Size cffsize ) /* CFF_Size */ { + FT_Memory memory = cffsize->face->memory; CFF_Size size = (CFF_Size)cffsize; CFF_Face face = (CFF_Face)size->root.face; CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = (CFF_Internal)cffsize->internal; + CFF_Internal internal = (CFF_Internal)cffsize->internal->module_data; if ( internal ) @@ -98,7 +101,7 @@ funcs->destroy( internal->subfonts[i - 1] ); } - /* `internal' is freed by destroy_size (in ftobjs.c) */ + FT_FREE( internal ); } } @@ -194,7 +197,7 @@ goto Exit; } - cffsize->internal = (FT_Size_Internal)(void*)internal; + cffsize->internal->module_data = internal; } size->strike_index = 0xFFFFFFFFUL; @@ -224,7 +227,7 @@ { CFF_Face face = (CFF_Face)size->face; CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = (CFF_Internal)size->internal; + CFF_Internal internal = (CFF_Internal)size->internal->module_data; FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; FT_UInt i; @@ -296,7 +299,7 @@ { CFF_Face cffface = (CFF_Face)size->face; CFF_Font font = (CFF_Font)cffface->extra.data; - CFF_Internal internal = (CFF_Internal)size->internal; + CFF_Internal internal = (CFF_Internal)size->internal->module_data; FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; FT_UInt i; @@ -517,6 +520,7 @@ goto Exit; /* check whether we have a valid OpenType file */ + FT_TRACE2(( " " )); error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { @@ -559,8 +563,8 @@ error = face->goto_table( face, TTAG_CFF2, stream, 0 ); if ( !error ) { - cff2 = 1; - face->isCFF2 = cff2; + cff2 = 1; + face->is_cff2 = cff2; } if ( FT_ERR_EQ( error, Table_Missing ) ) @@ -594,6 +598,7 @@ stream, face_index, cff, + face, pure_cff, cff2 ); if ( error ) @@ -683,62 +688,56 @@ } #endif /* FT_DEBUG_LEVEL_TRACE */ - - #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - - FT_Int instance_index = face_index >> 16; - - - if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && - mm && - instance_index > 0 ) { - FT_MM_Var* mm_var; - + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - error = mm->get_mm_var( cffface, NULL ); - if ( error ) - goto Exit; + FT_Int instance_index = face_index >> 16; - mm->get_var_blend( cffface, NULL, NULL, &mm_var ); - if ( mm_var->namedstyle ) + if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && + mm && + instance_index > 0 ) { - FT_Var_Named_Style* named_style; - FT_String* style_name; + FT_MM_Var* mm_var; - /* in `face_index', the instance index starts with value 1 */ - named_style = mm_var->namedstyle + instance_index - 1; - error = sfnt->get_name( face, - (FT_UShort)named_style->strid, - &style_name ); + error = mm->get_mm_var( cffface, NULL ); if ( error ) goto Exit; - /* set style name; if already set, replace it */ - if ( face->root.style_name ) - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; + mm->get_var_blend( cffface, NULL, NULL, NULL, &mm_var ); - /* finally, select the named instance */ - error = mm->set_var_design( cffface, - mm_var->num_axis, - named_style->coords ); - if ( error ) - goto Exit; + if ( mm_var->namedstyle ) + { + FT_Var_Named_Style* named_style; + FT_String* style_name; + + + /* in `face_index', the instance index starts with value 1 */ + named_style = mm_var->namedstyle + instance_index - 1; + error = sfnt->get_name( face, + (FT_UShort)named_style->strid, + &style_name ); + if ( error ) + goto Exit; + + /* set style name; if already set, replace it */ + if ( face->root.style_name ) + FT_FREE( face->root.style_name ); + face->root.style_name = style_name; + + /* finally, select the named instance */ + error = mm->set_var_design( cffface, + mm_var->num_axis, + named_style->coords ); + if ( error ) + goto Exit; + } } } - } - #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - - if ( !dict->has_font_matrix ) dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; @@ -1021,7 +1020,6 @@ cffface->style_flags = flags; } - #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ /* has unset this flag because of the 3.0 `post' table. */ @@ -1032,7 +1030,6 @@ if ( dict->cid_registry != 0xFFFFU && pure_cff ) cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; - /*******************************************************************/ /* */ /* Compute char maps. */ @@ -1164,6 +1161,8 @@ { CFF_Driver driver = (CFF_Driver)module; + FT_UInt32 seed; + /* set default property values, cf. `ftcffdrv.h' */ #ifdef CFF_CONFIG_OPTION_OLD_ENGINE @@ -1183,6 +1182,18 @@ driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; + /* compute random seed from some memory addresses */ + seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ + (FT_Offset)(char*)&module ^ + (FT_Offset)(char*)module->memory ); + seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); + + driver->random_seed = (FT_Int32)seed; + if ( driver->random_seed < 0 ) + driver->random_seed = -driver->random_seed; + else if ( driver->random_seed == 0 ) + driver->random_seed = 123456789; + return FT_Err_Ok; } diff --git a/Source/ThirdParty/FreeType/src/cff/cffobjs.h b/Source/ThirdParty/FreeType/src/cff/cffobjs.h index 9dc77536bd..1dba694c53 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffobjs.h +++ b/Source/ThirdParty/FreeType/src/cff/cffobjs.h @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -118,10 +118,10 @@ FT_BEGIN_HEADER { FT_DriverRec root; - FT_UInt hinting_engine; - FT_Bool no_stem_darkening; - - FT_Int darken_params[8]; + FT_UInt hinting_engine; + FT_Bool no_stem_darkening; + FT_Int darken_params[8]; + FT_Int32 random_seed; } CFF_DriverRec; diff --git a/Source/ThirdParty/FreeType/src/cff/cffparse.c b/Source/ThirdParty/FreeType/src/cff/cffparse.c index ee538c360d..e1511bdbd1 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffparse.c +++ b/Source/ThirdParty/FreeType/src/cff/cffparse.c @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (body) */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -448,9 +448,21 @@ /* 16.16 fixed point is used internally for CFF2 blend results. */ /* Since these are trusted values, a limit check is not needed. */ - /* After the 255, 4 bytes are in host order. */ - /* Blend result is rounded to integer. */ - return (FT_Long)( *( (FT_UInt32 *) ( d[0] + 1 ) ) + 0x8000U ) >> 16; + /* After the 255, 4 bytes give the number. */ + /* The blend value is converted to integer, with rounding; */ + /* due to the right-shift we don't need the lowest byte. */ +#if 0 + return (FT_Short)( + ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | + (FT_UInt32)*( d[0] + 4 ) ) + 0x8000U ) >> 16 ); +#else + return (FT_Short)( + ( ( ( (FT_UInt32)*( d[0] + 1 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 8 ) | + (FT_UInt32)*( d[0] + 3 ) ) + 0x80U ) >> 8 ); +#endif } else @@ -882,8 +894,6 @@ FT_Error error; - error = FT_ERR( Stack_Underflow ); - if ( !priv || !priv->subfont ) { error = FT_THROW( Invalid_File_Format ); @@ -1113,6 +1123,8 @@ #define CFF_FIELD_DELTA( code, name, max, id ) i++; #undef CFF_FIELD_CALLBACK #define CFF_FIELD_CALLBACK( code, name, id ) i++; +#undef CFF_FIELD_BLEND +#define CFF_FIELD_BLEND( code, id ) i++; #include "cfftoken.h" @@ -1160,6 +1172,17 @@ clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ i++; +#undef CFF_FIELD_BLEND +#define CFF_FIELD_BLEND( code_, id_ ) \ + clazz[i].kind = cff_kind_blend; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = 0; \ + clazz[i].size = 0; \ + clazz[i].reader = cff_parse_blend; \ + clazz[i].array_max = 0; \ + clazz[i].count_offset = 0; \ + i++; + #include "cfftoken.h" clazz[i].kind = 0; @@ -1210,6 +1233,18 @@ clazz[i].id = id_; \ i++; +#undef CFF_FIELD_BLEND +#define CFF_FIELD_BLEND( code_, id_ ) \ + clazz[i].kind = cff_kind_blend; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = 0; \ + clazz[i].size = 0; \ + clazz[i].reader = cff_parse_blend; \ + clazz[i].array_max = 0; \ + clazz[i].count_offset = 0; \ + clazz[i].id = id_; \ + i++; + #include "cfftoken.h" clazz[i].kind = 0; diff --git a/Source/ThirdParty/FreeType/src/cff/cffparse.h b/Source/ThirdParty/FreeType/src/cff/cffparse.h index 6088fec21c..83d1bba45f 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffparse.h +++ b/Source/ThirdParty/FreeType/src/cff/cffparse.h @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (specification) */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,8 +31,16 @@ FT_BEGIN_HEADER /* CFF uses constant parser stack size; */ /* CFF2 can increase from default 193 */ #define CFF_MAX_STACK_DEPTH 96 + + /* + * There are plans to remove the `maxstack' operator in a forthcoming + * revision of the CFF2 specification, increasing the (then static) stack + * size to 513. By making the default stack size equal to the maximum + * stack size, the operator is essentially disabled, which has the + * desired effect in FreeType. + */ #define CFF2_MAX_STACK 513 -#define CFF2_DEFAULT_STACK 193 +#define CFF2_DEFAULT_STACK 513 #define CFF_CODE_TOPDICT 0x1000 #define CFF_CODE_PRIVATE 0x2000 diff --git a/Source/ThirdParty/FreeType/src/cff/cffpic.c b/Source/ThirdParty/FreeType/src/cff/cffpic.c index a0bc34fd5f..4e9ba12b3f 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffpic.c +++ b/Source/ThirdParty/FreeType/src/cff/cffpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for cff module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cffpic.h b/Source/ThirdParty/FreeType/src/cff/cffpic.h index 4737b9e38a..5db39cd627 100644 --- a/Source/ThirdParty/FreeType/src/cff/cffpic.h +++ b/Source/ThirdParty/FreeType/src/cff/cffpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for cff module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -33,6 +33,7 @@ #define CFF_SERVICE_PROPERTIES_GET cff_service_properties #define CFF_SERVICES_GET cff_services #define CFF_SERVICE_MULTI_MASTERS_GET cff_service_multi_masters +#define CFF_SERVICE_METRICS_VAR_GET cff_service_metrics_variations #define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec #define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec #define CFF_FIELD_HANDLERS_GET cff_field_handlers @@ -46,22 +47,26 @@ #include FT_SERVICE_TT_CMAP_H #include FT_SERVICE_CID_H #include FT_SERVICE_PROPERTIES_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H FT_BEGIN_HEADER typedef struct CffModulePIC_ { - FT_ServiceDescRec* cff_services; - CFF_Field_Handler* cff_field_handlers; - FT_Service_PsInfoRec cff_service_ps_info; - FT_Service_GlyphDictRec cff_service_glyph_dict; - FT_Service_PsFontNameRec cff_service_ps_name; - FT_Service_TTCMapsRec cff_service_get_cmap_info; - FT_Service_CIDRec cff_service_cid_info; - FT_Service_PropertiesRec cff_service_properties; - FT_CMap_ClassRec cff_cmap_encoding_class_rec; - FT_CMap_ClassRec cff_cmap_unicode_class_rec; + FT_ServiceDescRec* cff_services; + CFF_Field_Handler* cff_field_handlers; + FT_Service_PsInfoRec cff_service_ps_info; + FT_Service_GlyphDictRec cff_service_glyph_dict; + FT_Service_PsFontNameRec cff_service_ps_name; + FT_Service_TTCMapsRec cff_service_get_cmap_info; + FT_Service_CIDRec cff_service_cid_info; + FT_Service_PropertiesRec cff_service_properties; + FT_Service_MultiMastersRec cff_service_multi_masters; + FT_Service_MetricsVariationsRec cff_service_metrics_variations; + FT_CMap_ClassRec cff_cmap_encoding_class_rec; + FT_CMap_ClassRec cff_cmap_unicode_class_rec; } CffModulePIC; @@ -83,6 +88,10 @@ FT_BEGIN_HEADER ( GET_PIC( library )->cff_service_properties ) #define CFF_SERVICES_GET \ ( GET_PIC( library )->cff_services ) +#define CFF_SERVICE_MULTI_MASTERS_GET \ + ( GET_PIC( library )->cff_service_multi_masters ) +#define CFF_SERVICE_METRICS_VAR_GET \ + ( GET_PIC( library )->cff_service_metrics_variations ) #define CFF_CMAP_ENCODING_CLASS_REC_GET \ ( GET_PIC( library )->cff_cmap_encoding_class_rec ) #define CFF_CMAP_UNICODE_CLASS_REC_GET \ diff --git a/Source/ThirdParty/FreeType/src/cff/cfftoken.h b/Source/ThirdParty/FreeType/src/cff/cfftoken.h index fd41c6c711..3222e933f1 100644 --- a/Source/ThirdParty/FreeType/src/cff/cfftoken.h +++ b/Source/ThirdParty/FreeType/src/cff/cfftoken.h @@ -4,7 +4,7 @@ /* */ /* CFF token definitions (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cff/cfftypes.h b/Source/ThirdParty/FreeType/src/cff/cfftypes.h index 4dae0f281e..74f569f08b 100644 --- a/Source/ThirdParty/FreeType/src/cff/cfftypes.h +++ b/Source/ThirdParty/FreeType/src/cff/cfftypes.h @@ -5,7 +5,7 @@ /* Basic OpenType/CFF type definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -112,8 +112,8 @@ FT_BEGIN_HEADER FT_UInt shortDeltaCount; /* not used; always zero */ #endif - FT_UInt regionIdxCount; /* number of regions in this var data */ - FT_UInt* regionIndices; /* array of `regionCount' indices; */ + FT_UInt regionIdxCount; /* number of region indexes */ + FT_UInt* regionIndices; /* array of `regionIdxCount' indices; */ /* these index `varRegionList' */ } CFF_VarData; @@ -321,6 +321,8 @@ FT_BEGIN_HEADER FT_Byte** local_subrs; /* array of pointers */ /* into Local Subrs INDEX data */ + FT_UInt32 random; + } CFF_SubFontRec; @@ -389,6 +391,7 @@ FT_BEGIN_HEADER /* since version 2.4.12 */ FT_Generic cf2_instance; + /* since version 2.7.1 */ CFF_VStoreRec vstore; /* parsed vstore structure */ } CFF_FontRec; diff --git a/Source/ThirdParty/FreeType/src/cid/ciderrs.h b/Source/ThirdParty/FreeType/src/cid/ciderrs.h index 1dc98c7cdd..709dc8cd1e 100644 --- a/Source/ThirdParty/FreeType/src/cid/ciderrs.h +++ b/Source/ThirdParty/FreeType/src/cid/ciderrs.h @@ -4,7 +4,7 @@ /* */ /* CID error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidgload.c b/Source/ThirdParty/FreeType/src/cid/cidgload.c index c7b95593ee..b96c33334d 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidgload.c +++ b/Source/ThirdParty/FreeType/src/cid/cidgload.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidgload.h b/Source/ThirdParty/FreeType/src/cid/cidgload.h index 62d664b3af..7f816b5bc7 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidgload.h +++ b/Source/ThirdParty/FreeType/src/cid/cidgload.h @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidload.c b/Source/ThirdParty/FreeType/src/cid/cidload.c index fc2a3cfe72..ff0722110d 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidload.c +++ b/Source/ThirdParty/FreeType/src/cid/cidload.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 font loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -461,6 +461,9 @@ FT_Byte* p; + if ( !num_subrs ) + continue; + /* reallocate offsets array if needed */ if ( num_subrs + 1 > max_offsets ) { diff --git a/Source/ThirdParty/FreeType/src/cid/cidload.h b/Source/ThirdParty/FreeType/src/cid/cidload.h index 680f0d8fc5..45a0e6df25 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidload.h +++ b/Source/ThirdParty/FreeType/src/cid/cidload.h @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 font loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidobjs.c b/Source/ThirdParty/FreeType/src/cid/cidobjs.c index 2d2600fd4c..ceda8ff97f 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidobjs.c +++ b/Source/ThirdParty/FreeType/src/cid/cidobjs.c @@ -4,7 +4,7 @@ /* */ /* CID objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -113,16 +113,16 @@ CID_Size size = (CID_Size)cidsize; - if ( cidsize->internal ) + if ( cidsize->internal->module_data ) { PSH_Globals_Funcs funcs; funcs = cid_size_get_globals_funcs( size ); if ( funcs ) - funcs->destroy( (PSH_Globals)cidsize->internal ); + funcs->destroy( (PSH_Globals)cidsize->internal->module_data ); - cidsize->internal = NULL; + cidsize->internal->module_data = NULL; } } @@ -145,7 +145,7 @@ error = funcs->create( cidsize->face->memory, priv, &globals ); if ( !error ) - cidsize->internal = (FT_Size_Internal)(void*)globals; + cidsize->internal->module_data = globals; } return error; @@ -164,7 +164,7 @@ funcs = cid_size_get_globals_funcs( (CID_Size)size ); if ( funcs ) - funcs->set_scale( (PSH_Globals)size->internal, + funcs->set_scale( (PSH_Globals)size->internal->module_data, size->metrics.x_scale, size->metrics.y_scale, 0, 0 ); diff --git a/Source/ThirdParty/FreeType/src/cid/cidobjs.h b/Source/ThirdParty/FreeType/src/cid/cidobjs.h index 5dd377a9f8..8bcf886e10 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidobjs.h +++ b/Source/ThirdParty/FreeType/src/cid/cidobjs.h @@ -4,7 +4,7 @@ /* */ /* CID objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidparse.c b/Source/ThirdParty/FreeType/src/cid/cidparse.c index 1b27b2e953..007609bbdf 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidparse.c +++ b/Source/ThirdParty/FreeType/src/cid/cidparse.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 parser (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidparse.h b/Source/ThirdParty/FreeType/src/cid/cidparse.h index 7268dc6ae8..20bebb942b 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidparse.h +++ b/Source/ThirdParty/FreeType/src/cid/cidparse.h @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 parser (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidriver.c b/Source/ThirdParty/FreeType/src/cid/cidriver.c index 257365681a..bb611a961e 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidriver.c +++ b/Source/ThirdParty/FreeType/src/cid/cidriver.c @@ -4,7 +4,7 @@ /* */ /* CID driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidriver.h b/Source/ThirdParty/FreeType/src/cid/cidriver.h index a359a78907..76640c57ba 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidriver.h +++ b/Source/ThirdParty/FreeType/src/cid/cidriver.h @@ -4,7 +4,7 @@ /* */ /* High-level CID driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/cidtoken.h b/Source/ThirdParty/FreeType/src/cid/cidtoken.h index 9c773fd094..653cc5586e 100644 --- a/Source/ThirdParty/FreeType/src/cid/cidtoken.h +++ b/Source/ThirdParty/FreeType/src/cid/cidtoken.h @@ -4,7 +4,7 @@ /* */ /* CID token definitions (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/cid/type1cid.c b/Source/ThirdParty/FreeType/src/cid/type1cid.c index de3bdf7705..93e6f810db 100644 --- a/Source/ThirdParty/FreeType/src/cid/type1cid.c +++ b/Source/ThirdParty/FreeType/src/cid/type1cid.c @@ -4,7 +4,7 @@ /* */ /* FreeType OpenType driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,13 +17,13 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "cidparse.c" + +#include "cidgload.c" #include "cidload.c" #include "cidobjs.c" +#include "cidparse.c" #include "cidriver.c" -#include "cidgload.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/README b/Source/ThirdParty/FreeType/src/gxvalid/README index d3ac49c3e2..7201459aaf 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/README +++ b/Source/ThirdParty/FreeType/src/gxvalid/README @@ -413,7 +413,7 @@ gxvalid: TrueType GX validator format assured for Windows and OS/2 support is only subtable format 0. The Microsoft TrueType specification also describes subtable format 2, but does not mention which platforms support - it. Aubtable formats 1, 3, and higher are documented as reserved + it. Subtable formats 1, 3, and higher are documented as reserved for future use. Therefore, the classic version can store subtable formats 0 and 2, at least. `ttfdump.exe', a font tool provided by Microsoft, ignores the subtable format written in the subtable @@ -518,7 +518,7 @@ gxvalid: TrueType GX validator ------------------------------------------------------------------------ -Copyright 2004-2016 by +Copyright 2004-2017 by suzuki toshiya, Masatake YAMATO, Red hat K.K., David Turner, Robert Wilhelm, and Werner Lemberg. diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.c index 7fb868cad1..da485141d3 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.c @@ -4,7 +4,7 @@ /* */ /* FreeType validator for TrueTypeGX/AAT tables (body only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ @@ -16,15 +16,17 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> -#include "gxvfeat.c" -#include "gxvcommn.c" #include "gxvbsln.c" -#include "gxvtrak.c" +#include "gxvcommn.c" +#include "gxvfeat.c" #include "gxvjust.c" +#include "gxvkern.c" +#include "gxvlcar.c" +#include "gxvmod.c" #include "gxvmort.c" #include "gxvmort0.c" #include "gxvmort1.c" @@ -37,11 +39,9 @@ #include "gxvmorx2.c" #include "gxvmorx4.c" #include "gxvmorx5.c" -#include "gxvkern.c" #include "gxvopbd.c" #include "gxvprop.c" -#include "gxvlcar.c" -#include "gxvmod.c" +#include "gxvtrak.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.h b/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.h index 7a3ab795ef..78116ef85a 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvalid.h @@ -2,9 +2,9 @@ /* */ /* gxvalid.h */ /* */ -/* TrueTyeeGX/AAT table validation (specification only). */ +/* TrueTypeGX/AAT table validation (specification only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvbsln.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvbsln.c index 493b20c31a..81dff7304d 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvbsln.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvbsln.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT bsln table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.c index b324bc602a..db0a91ea74 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common tables validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ @@ -454,7 +454,7 @@ } - /* ================= Segment Single Format 2 Loolup Table ============== */ + /* ================= Segment Single Format 2 Lookup Table ============== */ /* * Apple spec says: * diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.h b/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.h index 9470c8412b..10b1c800f0 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvcommn.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common tables validation (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxverror.h b/Source/ThirdParty/FreeType/src/gxvalid/gxverror.h index 2e53355ce4..80a2b8a262 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxverror.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxverror.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT validation module error codes (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.c index 5bff7c261d..2e3ec6f9be 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT feat table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.h b/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.h index 284bada891..8c0e847eb7 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvfeat.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT feat table validation (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvfgen.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvfgen.c index 667dac3cde..8cc08cd9c3 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvfgen.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvfgen.c @@ -5,7 +5,7 @@ /* Generate feature registry data for gxv `feat' validator. */ /* This program is derived from gxfeatreg.c in gxlayout. */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Masatake YAMATO and Redhat K.K. */ /* */ /* This file may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvjust.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvjust.c index 20d29bfbc8..c8cfd83eac 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvjust.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvjust.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT just table validation (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvkern.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvkern.c index ee1ab36f70..9f9037387d 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvkern.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvkern.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT kern table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvlcar.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvlcar.c index d31b6410bd..775d5229f2 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvlcar.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvlcar.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT lcar table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.c index 32fd84e141..84e9275baf 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType's TrueTypeGX/AAT validation module implementation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.h b/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.h index 8b82e91070..df25e60cb2 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmod.h @@ -5,7 +5,7 @@ /* FreeType's TrueTypeGX/AAT validation module implementation */ /* (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.c index 1209392049..184a6317c0 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT mort table validation (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.h b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.h index 5fd228212a..d0543adcc5 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common definition for mort table (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort0.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort0.c index e11f5ddc49..a75fad7768 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort0.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort0.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type0 (Indic Script Rearrangement) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort1.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort1.c index fd761d0692..361ef2262d 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort1.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort1.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type1 (Contextual Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort2.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort2.c index 08455dec6b..c17e51e323 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort2.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort2.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type2 (Ligature Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort4.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort4.c index 6f7bbb8710..041bab369f 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort4.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort4.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type4 (Non-Contextual Glyph Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort5.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort5.c index 54ddbe2b15..4751eceaa0 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmort5.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmort5.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type5 (Contextual Glyph Insertion) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.c index b626993f2d..2bb4f3b8b1 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT morx table validation (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.h b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.h index 9ba25c14a4..20cec58672 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.h +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common definition for morx table (specification). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx0.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx0.c index 4abb7368f2..e0a0a92438 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx0.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx0.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type0 (Indic Script Rearrangement) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx1.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx1.c index e581848c2b..9afebdbfa8 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx1.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx1.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type1 (Contextual Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx2.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx2.c index 9495cca489..3a60cf68a4 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx2.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx2.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type2 (Ligature Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx4.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx4.c index 3b7731bbce..29555685af 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx4.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx4.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx5.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx5.c index 0e96166c02..05c11417ef 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx5.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvmorx5.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type5 (Contextual Glyph Insertion) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvopbd.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvopbd.c index e3ba082e16..11580d8b2a 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvopbd.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvopbd.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT opbd table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvprop.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvprop.c index 61b3aeee30..7d398b7e66 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvprop.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvprop.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT prop table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/gxvalid/gxvtrak.c b/Source/ThirdParty/FreeType/src/gxvalid/gxvtrak.c index 0f07c04e2a..dd49825565 100644 --- a/Source/ThirdParty/FreeType/src/gxvalid/gxvtrak.c +++ b/Source/ThirdParty/FreeType/src/gxvalid/gxvtrak.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT trak table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/lzw/ftlzw.c b/Source/ThirdParty/FreeType/src/lzw/ftlzw.c index 6f5f897083..941f6cef4c 100644 --- a/Source/ThirdParty/FreeType/src/lzw/ftlzw.c +++ b/Source/ThirdParty/FreeType/src/lzw/ftlzw.c @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* Albert Chin-A-Young. */ /* */ /* based on code in `src/gzip/ftgzip.c' */ diff --git a/Source/ThirdParty/FreeType/src/lzw/ftzopen.c b/Source/ThirdParty/FreeType/src/lzw/ftzopen.c index a2cc453d65..486c546c14 100644 --- a/Source/ThirdParty/FreeType/src/lzw/ftzopen.c +++ b/Source/ThirdParty/FreeType/src/lzw/ftzopen.c @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/lzw/ftzopen.h b/Source/ThirdParty/FreeType/src/lzw/ftzopen.h index 1c38f1ab3d..a108862c0a 100644 --- a/Source/ThirdParty/FreeType/src/lzw/ftzopen.h +++ b/Source/ThirdParty/FreeType/src/lzw/ftzopen.h @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvalid.c b/Source/ThirdParty/FreeType/src/otvalid/otvalid.c index 932a974a31..312751a1f4 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvalid.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvalid.c @@ -4,7 +4,7 @@ /* */ /* FreeType validator for OpenType tables (body only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -15,8 +15,8 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> #include "otvbase.c" @@ -28,4 +28,5 @@ #include "otvmath.c" #include "otvmod.c" + /* END */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvalid.h b/Source/ThirdParty/FreeType/src/otvalid/otvalid.h index 93438a0639..f2969ccccc 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvalid.h +++ b/Source/ThirdParty/FreeType/src/otvalid/otvalid.h @@ -4,7 +4,7 @@ /* */ /* OpenType table validation (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvbase.c b/Source/ThirdParty/FreeType/src/otvalid/otvbase.c index e86e8bb2f0..3adad8439c 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvbase.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvbase.c @@ -4,7 +4,7 @@ /* */ /* OpenType BASE table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvcommn.c b/Source/ThirdParty/FreeType/src/otvalid/otvcommn.c index 6a684441d8..3407d2ad4a 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvcommn.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvcommn.c @@ -4,7 +4,7 @@ /* */ /* OpenType common tables validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvcommn.h b/Source/ThirdParty/FreeType/src/otvalid/otvcommn.h index 44e0c63793..10a603ebb9 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvcommn.h +++ b/Source/ThirdParty/FreeType/src/otvalid/otvcommn.h @@ -4,7 +4,7 @@ /* */ /* OpenType common tables validation (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otverror.h b/Source/ThirdParty/FreeType/src/otvalid/otverror.h index e7c8db0d58..699903987c 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otverror.h +++ b/Source/ThirdParty/FreeType/src/otvalid/otverror.h @@ -4,7 +4,7 @@ /* */ /* OpenType validation module error codes (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvgdef.c b/Source/ThirdParty/FreeType/src/otvalid/otvgdef.c index f19e300e51..27b9a69ca8 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvgdef.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvgdef.c @@ -4,7 +4,7 @@ /* */ /* OpenType GDEF table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvgpos.c b/Source/ThirdParty/FreeType/src/otvalid/otvgpos.c index e904ea5d6c..0fbcc2077c 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvgpos.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvgpos.c @@ -4,7 +4,7 @@ /* */ /* OpenType GPOS table validation (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvgpos.h b/Source/ThirdParty/FreeType/src/otvalid/otvgpos.h index 2c09e64f97..99b0ad3915 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvgpos.h +++ b/Source/ThirdParty/FreeType/src/otvalid/otvgpos.h @@ -4,7 +4,7 @@ /* */ /* OpenType GPOS table validator (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvgsub.c b/Source/ThirdParty/FreeType/src/otvalid/otvgsub.c index c2b28569f1..f9bd8dc5d8 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvgsub.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvgsub.c @@ -4,7 +4,7 @@ /* */ /* OpenType GSUB table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvjstf.c b/Source/ThirdParty/FreeType/src/otvalid/otvjstf.c index e19c1c1213..57a38f95c9 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvjstf.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvjstf.c @@ -4,7 +4,7 @@ /* */ /* OpenType JSTF table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvmath.c b/Source/ThirdParty/FreeType/src/otvalid/otvmath.c index 47e2f87c11..a14d369700 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvmath.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvmath.c @@ -4,7 +4,7 @@ /* */ /* OpenType MATH table validation (body). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Written by George Williams. */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvmod.c b/Source/ThirdParty/FreeType/src/otvalid/otvmod.c index aed5e9c6f8..35ffc43d3a 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvmod.c +++ b/Source/ThirdParty/FreeType/src/otvalid/otvmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType's OpenType validation module implementation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/otvalid/otvmod.h b/Source/ThirdParty/FreeType/src/otvalid/otvmod.h index e464030ab0..30d401ddca 100644 --- a/Source/ThirdParty/FreeType/src/otvalid/otvmod.h +++ b/Source/ThirdParty/FreeType/src/otvalid/otvmod.h @@ -5,7 +5,7 @@ /* FreeType's OpenType validation module implementation */ /* (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pcf/pcf.c b/Source/ThirdParty/FreeType/src/pcf/pcf.c index 11d5b7b2a0..8ffd6e280b 100644 --- a/Source/ThirdParty/FreeType/src/pcf/pcf.c +++ b/Source/ThirdParty/FreeType/src/pcf/pcf.c @@ -26,11 +26,11 @@ THE SOFTWARE. #define FT_MAKE_OPTION_SINGLE_OBJECT - - #include <ft2build.h> -#include "pcfutil.c" -#include "pcfread.c" + #include "pcfdrivr.c" +#include "pcfread.c" +#include "pcfutil.c" + /* END */ diff --git a/Source/ThirdParty/FreeType/src/pcf/pcf.h b/Source/ThirdParty/FreeType/src/pcf/pcf.h index c726e5ec6b..f0390cb1eb 100644 --- a/Source/ThirdParty/FreeType/src/pcf/pcf.h +++ b/Source/ThirdParty/FreeType/src/pcf/pcf.h @@ -163,6 +163,15 @@ FT_BEGIN_HEADER } PCF_FaceRec, *PCF_Face; + typedef struct PCF_DriverRec_ + { + FT_DriverRec root; + + FT_Bool no_long_family_names; + + } PCF_DriverRec, *PCF_Driver; + + /* macros for pcf font format */ #define LSBFirst 0 diff --git a/Source/ThirdParty/FreeType/src/pcf/pcfdrivr.c b/Source/ThirdParty/FreeType/src/pcf/pcfdrivr.c index d60cc3ee53..9f4d36d111 100644 --- a/Source/ThirdParty/FreeType/src/pcf/pcfdrivr.c +++ b/Source/ThirdParty/FreeType/src/pcf/pcfdrivr.c @@ -49,6 +49,8 @@ THE SOFTWARE. #include FT_SERVICE_BDF_H #include FT_SERVICE_FONT_FORMAT_H +#include FT_SERVICE_PROPERTIES_H +#include FT_PCF_DRIVER_H /*************************************************************************/ @@ -286,6 +288,7 @@ THE SOFTWARE. /* this didn't work, try gzip support! */ + FT_TRACE2(( " ... try gzip stream\n" )); error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) goto Fail; @@ -301,6 +304,7 @@ THE SOFTWARE. /* this didn't work, try LZW support! */ + FT_TRACE2(( " ... try LZW stream\n" )); error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) goto Fail; @@ -316,6 +320,7 @@ THE SOFTWARE. /* this didn't work, try Bzip2 support! */ + FT_TRACE2(( " ... try Bzip2 stream\n" )); error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) goto Fail; @@ -521,11 +526,6 @@ THE SOFTWARE. bitmap->num_grays = 1; bitmap->pixel_mode = FT_PIXEL_MODE_MONO; - FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n", - PCF_BIT_ORDER( face->bitmapsFormat ), - PCF_BYTE_ORDER( face->bitmapsFormat ), - PCF_GLYPH_PAD( face->bitmapsFormat ) )); - switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) { case 1: @@ -627,19 +627,23 @@ THE SOFTWARE. } else { - if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) + if ( prop->value.l > 0x7FFFFFFFL || + prop->value.l < ( -1 - 0x7FFFFFFFL ) ) { - FT_TRACE1(( "pcf_get_bdf_property: " )); - FT_TRACE1(( "too large integer 0x%x is truncated\n" )); + FT_TRACE1(( "pcf_get_bdf_property:" )); + FT_TRACE1(( " too large integer 0x%x is truncated\n" )); } - /* Apparently, the PCF driver loads all properties as signed integers! - * This really doesn't seem to be a problem, because this is - * sufficient for any meaningful values. + + /* + * The PCF driver loads all properties as signed integers. + * This really doesn't seem to be a problem, because this is + * sufficient for any meaningful values. */ aproperty->type = BDF_PROPERTY_TYPE_INTEGER; aproperty->u.integer = (FT_Int32)prop->value.l; } - return 0; + + return FT_Err_Ok; } return FT_THROW( Invalid_Argument ); @@ -654,7 +658,7 @@ THE SOFTWARE. *acharset_encoding = face->charset_encoding; *acharset_registry = face->charset_registry; - return 0; + return FT_Err_Ok; } @@ -665,6 +669,116 @@ THE SOFTWARE. }; + /* + * PROPERTY SERVICE + * + */ + static FT_Error + pcf_property_set( FT_Module module, /* PCF_Driver */ + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + FT_Error error = FT_Err_Ok; + PCF_Driver driver = (PCF_Driver)module; + +#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + FT_UNUSED( value_is_string ); +#endif + + + if ( !ft_strcmp( property_name, "no-long-family-names" ) ) + { +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + long lfn = ft_strtol( s, NULL, 10 ); + + + if ( lfn == 0 ) + driver->no_long_family_names = 0; + else if ( lfn == 1 ) + driver->no_long_family_names = 1; + else + return FT_THROW( Invalid_Argument ); + } + else +#endif + { + FT_Bool* no_long_family_names = (FT_Bool*)value; + + + driver->no_long_family_names = *no_long_family_names; + } + + return error; + } + +#else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_UNUSED( module ); + FT_UNUSED( value ); + FT_UNUSED( value_is_string ); +#ifndef FT_DEBUG_LEVEL_TRACE + FT_UNUSED( property_name ); +#endif + +#endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_TRACE0(( "pcf_property_set: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + static FT_Error + pcf_property_get( FT_Module module, /* PCF_Driver */ + const char* property_name, + const void* value ) + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + FT_Error error = FT_Err_Ok; + PCF_Driver driver = (PCF_Driver)module; + + + if ( !ft_strcmp( property_name, "no-long-family-names" ) ) + { + FT_Bool no_long_family_names = driver->no_long_family_names; + FT_Bool* val = (FT_Bool*)value; + + + *val = no_long_family_names; + + return error; + } + +#else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_UNUSED( module ); + FT_UNUSED( value ); +#ifndef FT_DEBUG_LEVEL_TRACE + FT_UNUSED( property_name ); +#endif + +#endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_TRACE0(( "pcf_property_get: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + pcf_service_properties, + + (FT_Properties_SetFunc)pcf_property_set, /* set_property */ + (FT_Properties_GetFunc)pcf_property_get ) /* get_property */ + + /* * * SERVICE LIST @@ -675,6 +789,7 @@ THE SOFTWARE. { { FT_SERVICE_ID_BDF, &pcf_service_bdf }, { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF }, + { FT_SERVICE_ID_PROPERTIES, &pcf_service_properties }, { NULL, NULL } }; @@ -689,22 +804,45 @@ THE SOFTWARE. } + FT_CALLBACK_DEF( FT_Error ) + pcf_driver_init( FT_Module module ) /* PCF_Driver */ + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + PCF_Driver driver = (PCF_Driver)module; + + + driver->no_long_family_names = 0; +#else + FT_UNUSED( module ); +#endif + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + pcf_driver_done( FT_Module module ) /* PCF_Driver */ + { + FT_UNUSED( module ); + } + + FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec pcf_driver_class = { { FT_MODULE_FONT_DRIVER | FT_MODULE_DRIVER_NO_OUTLINES, - sizeof ( FT_DriverRec ), + sizeof ( PCF_DriverRec ), "pcf", 0x10000L, 0x20000L, - NULL, /* module-specific interface */ + NULL, /* module-specific interface */ - NULL, /* FT_Module_Constructor module_init */ - NULL, /* FT_Module_Destructor module_done */ + pcf_driver_init, /* FT_Module_Constructor module_init */ + pcf_driver_done, /* FT_Module_Destructor module_done */ pcf_driver_requester /* FT_Module_Requester get_interface */ }, diff --git a/Source/ThirdParty/FreeType/src/pcf/pcfread.c b/Source/ThirdParty/FreeType/src/pcf/pcfread.c index 95ee570187..3eacf2baf6 100644 --- a/Source/ThirdParty/FreeType/src/pcf/pcfread.c +++ b/Source/ThirdParty/FreeType/src/pcf/pcfread.c @@ -50,8 +50,15 @@ THE SOFTWARE. #ifdef FT_DEBUG_LEVEL_TRACE static const char* const tableNames[] = { - "prop", "accl", "mtrcs", "bmps", "imtrcs", - "enc", "swidth", "names", "accel" + "properties", + "accelerators", + "metrics", + "bitmaps", + "ink metrics", + "encodings", + "swidths", + "glyph names", + "BDF accelerators" }; #endif @@ -109,22 +116,20 @@ THE SOFTWARE. if ( stream->size < 16 ) return FT_THROW( Invalid_File_Format ); - /* We need 16 bytes per TOC entry. Additionally, as a */ - /* heuristic protection against gzip bombs (i.e., very */ - /* small input files that expand to insanely large */ - /* files), we limit the number of TOC entries to 1024. */ - if ( toc->count > stream->size >> 4 || - toc->count > 1024 ) + /* we need 16 bytes per TOC entry, */ + /* and there can be most 9 tables */ + if ( toc->count > ( stream->size >> 4 ) || + toc->count > 9 ) { FT_TRACE0(( "pcf_read_TOC: adjusting number of tables" " (from %d to %d)\n", toc->count, - FT_MIN( stream->size >> 4, 1024 ) )); - toc->count = FT_MIN( stream->size >> 4, 1024 ); + FT_MIN( stream->size >> 4, 9 ) )); + toc->count = FT_MIN( stream->size >> 4, 9 ); } if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) - return FT_THROW( Out_Of_Memory ); + return error; tables = face->toc.tables; for ( n = 0; n < toc->count; n++ ) @@ -237,8 +242,8 @@ THE SOFTWARE. if ( tables[i].type == (FT_UInt)( 1 << j ) ) name = tableNames[j]; - FT_TRACE4(( " %d: type=%s, format=0x%X, " - "size=%ld (0x%lX), offset=%ld (0x%lX)\n", + FT_TRACE4(( " %d: type=%s, format=0x%X," + " size=%ld (0x%lX), offset=%ld (0x%lX)\n", i, name, tables[i].format, tables[i].size, tables[i].size, @@ -348,6 +353,17 @@ THE SOFTWARE. metric->attributes = 0; } + FT_TRACE5(( " width=%d," + " lsb=%d, rsb=%d," + " ascent=%d, descent=%d," + " attributes=%d\n", + metric->characterWidth, + metric->leftSideBearing, + metric->rightSideBearing, + metric->ascent, + metric->descent, + metric->attributes )); + Exit: return error; } @@ -466,7 +482,7 @@ THE SOFTWARE. { PCF_ParseProperty props = NULL; PCF_Property properties = NULL; - FT_ULong nprops, i; + FT_ULong nprops, orig_nprops, i; FT_ULong format, size; FT_Error error; FT_Memory memory = FT_FACE( face )->memory; @@ -486,32 +502,43 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_properties:\n" )); - - FT_TRACE4(( " format = %ld\n", format )); + FT_TRACE4(( "pcf_get_properties:\n" + " format: 0x%lX (%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) goto Bail; if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_ULONG( nprops ); + (void)FT_READ_ULONG( orig_nprops ); else - (void)FT_READ_ULONG_LE( nprops ); + (void)FT_READ_ULONG_LE( orig_nprops ); if ( error ) goto Bail; - FT_TRACE4(( " nprop = %d (truncate %d props)\n", - (int)nprops, nprops - (FT_ULong)(int)nprops )); - - nprops = (FT_ULong)(int)nprops; + FT_TRACE4(( " number of properties: %ld\n", orig_nprops )); /* rough estimate */ - if ( nprops > size / PCF_PROPERTY_SIZE ) + if ( orig_nprops > size / PCF_PROPERTY_SIZE ) { error = FT_THROW( Invalid_Table ); goto Bail; } + /* as a heuristic limit to avoid excessive allocation in */ + /* gzip bombs (i.e., very small, invalid input data that */ + /* pretends to expand to an insanely large file) we only */ + /* load the first 256 properties */ + if ( orig_nprops > 256 ) + { + FT_TRACE0(( "pcf_get_properties:" + " only loading first 256 properties\n" )); + nprops = 256; + } + else + nprops = orig_nprops; + face->nprops = (int)nprops; if ( FT_NEW_ARRAY( props, nprops ) ) @@ -531,14 +558,23 @@ THE SOFTWARE. } } + /* this skip will only work if we really have an extremely large */ + /* number of properties; it will fail for fake data, avoiding an */ + /* unnecessarily large allocation later on */ + if ( FT_STREAM_SKIP( ( orig_nprops - nprops ) * PCF_PROPERTY_SIZE ) ) + { + error = FT_THROW( Invalid_Stream_Skip ); + goto Bail; + } + /* pad the property array */ /* */ /* clever here - nprops is the same as the number of odd-units read, */ /* as only isStringProp are odd length (Keith Packard) */ /* */ - if ( nprops & 3 ) + if ( orig_nprops & 3 ) { - i = 4 - ( nprops & 3 ); + i = 4 - ( orig_nprops & 3 ); if ( FT_STREAM_SKIP( i ) ) { error = FT_THROW( Invalid_Stream_Skip ); @@ -553,15 +589,24 @@ THE SOFTWARE. if ( error ) goto Bail; - FT_TRACE4(( " string_size = %ld\n", string_size )); + FT_TRACE4(( " string size: %ld\n", string_size )); /* rough estimate */ - if ( string_size > size - nprops * PCF_PROPERTY_SIZE ) + if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE ) { error = FT_THROW( Invalid_Table ); goto Bail; } + /* the strings in the `strings' array are PostScript strings, */ + /* which can have a maximum length of 65536 characters each */ + if ( string_size > 16777472 ) /* 256 * (65536 + 1) */ + { + FT_TRACE0(( "pcf_get_properties:" + " loading only 16777472 bytes of strings array\n" )); + string_size = 16777472; + } + /* allocate one more byte so that we have a final null byte */ if ( FT_NEW_ARRAY( strings, string_size + 1 ) ) goto Bail; @@ -575,6 +620,7 @@ THE SOFTWARE. face->properties = properties; + FT_TRACE4(( "\n" )); for ( i = 0; i < nprops; i++ ) { FT_Long name_offset = props[i].name; @@ -637,7 +683,7 @@ THE SOFTWARE. FT_Memory memory = FT_FACE( face )->memory; FT_ULong format, size; PCF_Metric metrics = NULL; - FT_ULong nmetrics, i; + FT_ULong nmetrics, orig_nmetrics, i; error = pcf_seek_to_table_type( stream, @@ -652,6 +698,13 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; + FT_TRACE4(( "pcf_get_metrics:\n" + " format: 0x%lX (%s, %s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", + PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ? + "compressed" : "uncompressed" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) return FT_THROW( Invalid_File_Format ); @@ -659,61 +712,70 @@ THE SOFTWARE. if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_ULONG( nmetrics ); + (void)FT_READ_ULONG( orig_nmetrics ); else - (void)FT_READ_ULONG_LE( nmetrics ); + (void)FT_READ_ULONG_LE( orig_nmetrics ); } else { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_USHORT( nmetrics ); + (void)FT_READ_USHORT( orig_nmetrics ); else - (void)FT_READ_USHORT_LE( nmetrics ); + (void)FT_READ_USHORT_LE( orig_nmetrics ); } if ( error ) return FT_THROW( Invalid_File_Format ); - face->nmetrics = nmetrics; - - if ( !nmetrics ) - return FT_THROW( Invalid_Table ); - - FT_TRACE4(( "pcf_get_metrics:\n" )); - - FT_TRACE4(( " number of metrics: %d\n", nmetrics )); + FT_TRACE4(( " number of metrics: %ld\n", orig_nmetrics )); /* rough estimate */ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { - if ( nmetrics > size / PCF_METRIC_SIZE ) + if ( orig_nmetrics > size / PCF_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } else { - if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) + if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } + if ( !orig_nmetrics ) + return FT_THROW( Invalid_Table ); + + /* PCF is a format from ancient times; Unicode was in its */ + /* infancy, and widely used two-byte character sets for CJK */ + /* scripts (Big 5, GB 2312, JIS X 0208, etc.) did have at most */ + /* 15000 characters. Even the more exotic CNS 11643 and CCCII */ + /* standards, which were essentially three-byte character sets, */ + /* provided less then 65536 assigned characters. */ + /* */ + /* While technically possible to have a larger number of glyphs */ + /* in PCF files, we thus limit the number to 65536. */ + if ( orig_nmetrics > 65536 ) + { + FT_TRACE0(( "pcf_get_metrics:" + " only loading first 65536 metrics\n" )); + nmetrics = 65536; + } + else + nmetrics = orig_nmetrics; + + face->nmetrics = nmetrics; + if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) - return FT_THROW( Out_Of_Memory ); + return error; metrics = face->metrics; + + FT_TRACE4(( "\n" )); for ( i = 0; i < nmetrics; i++, metrics++ ) { + FT_TRACE5(( " idx %ld:", i )); error = pcf_get_metric( stream, format, metrics ); metrics->bits = 0; - FT_TRACE5(( " idx %d: width=%d, " - "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", - i, - metrics->characterWidth, - metrics->leftSideBearing, - metrics->rightSideBearing, - metrics->ascent, - metrics->descent, - metrics->attributes )); - if ( error ) break; @@ -721,7 +783,7 @@ THE SOFTWARE. /* compute a glyph's bitmap dimensions, thus setting them to zero in */ /* case of an error disables this particular glyph only */ if ( metrics->rightSideBearing < metrics->leftSideBearing || - metrics->ascent + metrics->descent < 0 ) + metrics->ascent < -metrics->descent ) { metrics->characterWidth = 0; metrics->leftSideBearing = 0; @@ -751,7 +813,7 @@ THE SOFTWARE. FT_Long* offsets = NULL; FT_Long bitmapSizes[GLYPHPADOPTIONS]; FT_ULong format, size; - FT_ULong nbitmaps, i, sizebitmaps = 0; + FT_ULong nbitmaps, orig_nbitmaps, i, sizebitmaps = 0; error = pcf_seek_to_table_type( stream, @@ -769,18 +831,40 @@ THE SOFTWARE. format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - nbitmaps = FT_GET_ULONG(); + orig_nbitmaps = FT_GET_ULONG(); else - nbitmaps = FT_GET_ULONG_LE(); + orig_nbitmaps = FT_GET_ULONG_LE(); FT_Stream_ExitFrame( stream ); + FT_TRACE4(( "pcf_get_bitmaps:\n" + " format: 0x%lX\n" + " (%s, %s,\n" + " padding=%d bits, scanning=%d bits)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst + ? "most significant byte first" + : "least significant byte first", + PCF_BIT_ORDER( format ) == MSBFirst + ? "most significant bit first" + : "least significant bit first", + 8 << PCF_GLYPH_PAD_INDEX( format ), + 8 << PCF_SCAN_UNIT_INDEX( format ) )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); - FT_TRACE4(( "pcf_get_bitmaps:\n" )); + FT_TRACE4(( " number of bitmaps: %ld\n", orig_nbitmaps )); - FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps )); + /* see comment in `pcf_get_metrics' */ + if ( orig_nbitmaps > 65536 ) + { + FT_TRACE0(( "pcf_get_bitmaps:" + " only loading first 65536 bitmaps\n" )); + nbitmaps = 65536; + } + else + nbitmaps = orig_nbitmaps; if ( nbitmaps != face->nmetrics ) return FT_THROW( Invalid_File_Format ); @@ -788,6 +872,7 @@ THE SOFTWARE. if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) return error; + FT_TRACE5(( "\n" )); for ( i = 0; i < nbitmaps; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) @@ -795,7 +880,7 @@ THE SOFTWARE. else (void)FT_READ_LONG_LE( offsets[i] ); - FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n", + FT_TRACE5(( " bitmap %ld: offset %ld (0x%lX)\n", i, offsets[i], offsets[i] )); } if ( error ) @@ -812,17 +897,19 @@ THE SOFTWARE. sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; - FT_TRACE4(( " padding %d implies a size of %ld\n", - i, bitmapSizes[i] )); + FT_TRACE4(( " %ld-bit padding implies a size of %ld\n", + 8 << i, bitmapSizes[i] )); } - FT_TRACE4(( " %d bitmaps, padding index %ld\n", + FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n", nbitmaps, - PCF_GLYPH_PAD_INDEX( format ) )); - FT_TRACE4(( " bitmap size = %d\n", sizebitmaps )); + 8 << PCF_GLYPH_PAD_INDEX( format ) )); + FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps )); FT_UNUSED( sizebitmaps ); /* only used for debugging */ + /* right now, we only check the bitmap offsets; */ + /* actual bitmaps are only loaded on demand */ for ( i = 0; i < nbitmaps; i++ ) { /* rough estimate */ @@ -830,7 +917,7 @@ THE SOFTWARE. ( (FT_ULong)offsets[i] > size ) ) { FT_TRACE0(( "pcf_get_bitmaps:" - " invalid offset to bitmap data of glyph %d\n", i )); + " invalid offset to bitmap data of glyph %ld\n", i )); } else face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i]; @@ -894,10 +981,20 @@ THE SOFTWARE. FT_Stream_ExitFrame( stream ); + FT_TRACE4(( "pcf_get_encodings:\n" + " format: 0x%lX (%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); - /* sanity checks */ + FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n" + " firstRow 0x%X, lastRow 0x%X\n", + firstCol, lastCol, + firstRow, lastRow )); + + /* sanity checks; we limit numbers of rows and columns to 256 */ if ( firstCol < 0 || firstCol > lastCol || lastCol > 0xFF || @@ -906,21 +1003,18 @@ THE SOFTWARE. lastRow > 0xFF ) return FT_THROW( Invalid_Table ); - FT_TRACE4(( "pdf_get_encodings:\n" )); - - FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", - firstCol, lastCol, firstRow, lastRow )); - nencoding = (FT_ULong)( lastCol - firstCol + 1 ) * (FT_ULong)( lastRow - firstRow + 1 ); if ( FT_NEW_ARRAY( encoding, nencoding ) ) - return FT_THROW( Out_Of_Memory ); + return error; error = FT_Stream_EnterFrame( stream, 2 * nencoding ); if ( error ) goto Bail; + FT_TRACE5(( "\n" )); + k = 0; for ( i = firstRow; i <= lastRow; i++ ) { @@ -1029,6 +1123,15 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; + FT_TRACE4(( "pcf_get_accel%s:\n" + " format: 0x%lX (%s, %s)\n", + type == PCF_BDF_ACCELERATORS ? " (getting BDF accelerators)" + : "", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", + PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ? + "accelerated" : "not accelerated" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) goto Bail; @@ -1044,12 +1147,29 @@ THE SOFTWARE. goto Bail; } + FT_TRACE5(( " noOverlap=%s, constantMetrics=%s," + " terminalFont=%s, constantWidth=%s\n" + " inkInside=%s, inkMetrics=%s, drawDirection=%s\n" + " fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n", + accel->noOverlap ? "yes" : "no", + accel->constantMetrics ? "yes" : "no", + accel->terminalFont ? "yes" : "no", + accel->constantWidth ? "yes" : "no", + accel->inkInside ? "yes" : "no", + accel->inkMetrics ? "yes" : "no", + accel->drawDirection ? "RTL" : "LTR", + accel->fontAscent, + accel->fontDescent, + accel->maxOverlap )); + + FT_TRACE5(( " minbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->minbounds) ); if ( error ) goto Bail; + FT_TRACE5(( " maxbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->maxbounds) ); @@ -1058,12 +1178,14 @@ THE SOFTWARE. if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) { + FT_TRACE5(( " ink minbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->ink_minbounds) ); if ( error ) goto Bail; + FT_TRACE5(( " ink maxbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->ink_maxbounds) ); @@ -1072,7 +1194,7 @@ THE SOFTWARE. } else { - accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ + accel->ink_minbounds = accel->minbounds; accel->ink_maxbounds = accel->maxbounds; } @@ -1271,57 +1393,75 @@ THE SOFTWARE. prop = pcf_find_property( face, "FAMILY_NAME" ); if ( prop && prop->isString ) { - /* Prepend the foundry name plus a space to the family name. */ - /* There are many fonts just called `Fixed' which look completely */ - /* different, and which have nothing to do with each other. When */ - /* selecting `Fixed' in KDE or Gnome one gets results that appear */ - /* rather random, the style changes often if one changes the size */ - /* and one cannot select some fonts at all. */ - /* */ - /* We also check whether we have `wide' characters; all put */ - /* together, we get family names like `Sony Fixed' or `Misc Fixed */ - /* Wide'. */ - PCF_Property foundry_prop, point_size_prop, average_width_prop; - - int l = ft_strlen( prop->value.atom ) + 1; - int wide = 0; - - - foundry_prop = pcf_find_property( face, "FOUNDRY" ); - point_size_prop = pcf_find_property( face, "POINT_SIZE" ); - average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" ); - - if ( point_size_prop && average_width_prop ) + +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + PCF_Driver driver = (PCF_Driver)FT_FACE_DRIVER( face ); + + + if ( !driver->no_long_family_names ) { - if ( average_width_prop->value.l >= point_size_prop->value.l ) + /* Prepend the foundry name plus a space to the family name. */ + /* There are many fonts just called `Fixed' which look */ + /* completely different, and which have nothing to do with each */ + /* other. When selecting `Fixed' in KDE or Gnome one gets */ + /* results that appear rather random, the style changes often if */ + /* one changes the size and one cannot select some fonts at all. */ + /* */ + /* We also check whether we have `wide' characters; all put */ + /* together, we get family names like `Sony Fixed' or `Misc */ + /* Fixed Wide'. */ + + PCF_Property foundry_prop, point_size_prop, average_width_prop; + + int l = ft_strlen( prop->value.atom ) + 1; + int wide = 0; + + + foundry_prop = pcf_find_property( face, "FOUNDRY" ); + point_size_prop = pcf_find_property( face, "POINT_SIZE" ); + average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" ); + + if ( point_size_prop && average_width_prop ) { - /* This font is at least square shaped or even wider */ - wide = 1; - l += ft_strlen( " Wide" ); + if ( average_width_prop->value.l >= point_size_prop->value.l ) + { + /* This font is at least square shaped or even wider */ + wide = 1; + l += ft_strlen( " Wide" ); + } } - } - if ( foundry_prop && foundry_prop->isString ) - { - l += ft_strlen( foundry_prop->value.atom ) + 1; + if ( foundry_prop && foundry_prop->isString ) + { + l += ft_strlen( foundry_prop->value.atom ) + 1; - if ( FT_NEW_ARRAY( root->family_name, l ) ) - goto Exit; + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + + ft_strcpy( root->family_name, foundry_prop->value.atom ); + ft_strcat( root->family_name, " " ); + ft_strcat( root->family_name, prop->value.atom ); + } + else + { + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + + ft_strcpy( root->family_name, prop->value.atom ); + } - ft_strcpy( root->family_name, foundry_prop->value.atom ); - ft_strcat( root->family_name, " " ); - ft_strcat( root->family_name, prop->value.atom ); + if ( wide ) + ft_strcat( root->family_name, " Wide" ); } else + +#endif /* PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + { - if ( FT_NEW_ARRAY( root->family_name, l ) ) + if ( FT_STRDUP( root->family_name, prop->value.atom ) ) goto Exit; - - ft_strcpy( root->family_name, prop->value.atom ); } - - if ( wide ) - ft_strcat( root->family_name, " Wide" ); } else root->family_name = NULL; diff --git a/Source/ThirdParty/FreeType/src/pfr/pfr.c b/Source/ThirdParty/FreeType/src/pfr/pfr.c index 1a433960a5..4f31f5d9bc 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfr.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfr.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR driver component. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -15,15 +15,16 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> -#include "pfrload.c" -#include "pfrgload.c" #include "pfrcmap.c" -#include "pfrobjs.c" #include "pfrdrivr.c" +#include "pfrgload.c" +#include "pfrload.c" +#include "pfrobjs.c" #include "pfrsbit.c" + /* END */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrcmap.c b/Source/ThirdParty/FreeType/src/pfr/pfrcmap.c index f1f9c53b90..1d6b15be48 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrcmap.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfrcmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR cmap handling (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrcmap.h b/Source/ThirdParty/FreeType/src/pfr/pfrcmap.h index 4a8a4d0a67..957bf65b4c 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrcmap.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrcmap.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR cmap handling (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.c b/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.c index 2316cd3e72..195cdb76ac 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR driver interface (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.h b/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.h index 32b2d9eab3..b81d56017e 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrdrivr.h @@ -4,7 +4,7 @@ /* */ /* High-level Type PFR driver interface (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrerror.h b/Source/ThirdParty/FreeType/src/pfr/pfrerror.h index 9305f8fb58..ef044e32c9 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrerror.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrerror.h @@ -4,7 +4,7 @@ /* */ /* PFR error codes (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrgload.c b/Source/ThirdParty/FreeType/src/pfr/pfrgload.c index f9cd1f63bb..93f5fc7090 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrgload.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfrgload.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR glyph loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrgload.h b/Source/ThirdParty/FreeType/src/pfr/pfrgload.h index 908d4378a4..6612323871 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrgload.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrgload.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR glyph loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrload.c b/Source/ThirdParty/FreeType/src/pfr/pfrload.c index aad759af13..4f84165828 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrload.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfrload.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrload.h b/Source/ThirdParty/FreeType/src/pfr/pfrload.h index 0f7a2bb239..f9475ae062 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrload.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrload.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrobjs.c b/Source/ThirdParty/FreeType/src/pfr/pfrobjs.c index 0491d13df7..4b1703f51c 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrobjs.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfrobjs.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR object methods (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrobjs.h b/Source/ThirdParty/FreeType/src/pfr/pfrobjs.h index 335aca8854..d6ad6562df 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrobjs.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrobjs.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR object methods (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrsbit.c b/Source/ThirdParty/FreeType/src/pfr/pfrsbit.c index f9dbf734b0..54e7d0e6cc 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrsbit.c +++ b/Source/ThirdParty/FreeType/src/pfr/pfrsbit.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR bitmap loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrsbit.h b/Source/ThirdParty/FreeType/src/pfr/pfrsbit.h index 676ad55a95..fc270f50a8 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrsbit.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrsbit.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR bitmap loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pfr/pfrtypes.h b/Source/ThirdParty/FreeType/src/pfr/pfrtypes.h index bd6c2cd30c..c3d542c209 100644 --- a/Source/ThirdParty/FreeType/src/pfr/pfrtypes.h +++ b/Source/ThirdParty/FreeType/src/pfr/pfrtypes.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR data structures (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/afmparse.c b/Source/ThirdParty/FreeType/src/psaux/afmparse.c index 9fb0ac0e2b..ff2cc8cf08 100644 --- a/Source/ThirdParty/FreeType/src/psaux/afmparse.c +++ b/Source/ThirdParty/FreeType/src/psaux/afmparse.c @@ -4,7 +4,7 @@ /* */ /* AFM parser (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,8 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_POSTSCRIPT_AUX_H +#ifndef T1_CONFIG_OPTION_NO_AFM + #include "afmparse.h" #include "psconv.h" @@ -973,5 +975,12 @@ return error; } +#else /* T1_CONFIG_OPTION_NO_AFM */ + + /* ANSI C doesn't like empty source files */ + typedef int _afm_parse_dummy; + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + /* END */ diff --git a/Source/ThirdParty/FreeType/src/psaux/afmparse.h b/Source/ThirdParty/FreeType/src/psaux/afmparse.h index 6d8b193ffc..cd2beb7804 100644 --- a/Source/ThirdParty/FreeType/src/psaux/afmparse.h +++ b/Source/ThirdParty/FreeType/src/psaux/afmparse.h @@ -4,7 +4,7 @@ /* */ /* AFM parser (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psaux.c b/Source/ThirdParty/FreeType/src/psaux/psaux.c index 33b462ef15..c373aa7d5b 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psaux.c +++ b/Source/ThirdParty/FreeType/src/psaux/psaux.c @@ -4,7 +4,7 @@ /* */ /* FreeType auxiliary PostScript driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,18 +17,14 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "psobjs.c" -#include "psauxmod.c" -#include "t1decode.c" -#include "t1cmap.c" -#ifndef T1_CONFIG_OPTION_NO_AFM #include "afmparse.c" -#endif - +#include "psauxmod.c" #include "psconv.c" +#include "psobjs.c" +#include "t1cmap.c" +#include "t1decode.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psauxerr.h b/Source/ThirdParty/FreeType/src/psaux/psauxerr.h index 9739157fc4..1d7ac6001b 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psauxerr.h +++ b/Source/ThirdParty/FreeType/src/psaux/psauxerr.h @@ -4,7 +4,7 @@ /* */ /* PS auxiliary module error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psauxmod.c b/Source/ThirdParty/FreeType/src/psaux/psauxmod.c index b1b8b19c3d..1f589cefc2 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psauxmod.c +++ b/Source/ThirdParty/FreeType/src/psaux/psauxmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType auxiliary PostScript module implementation (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psauxmod.h b/Source/ThirdParty/FreeType/src/psaux/psauxmod.h index b1dbb06904..926f37eba5 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psauxmod.h +++ b/Source/ThirdParty/FreeType/src/psaux/psauxmod.h @@ -4,7 +4,7 @@ /* */ /* FreeType auxiliary PostScript module implementation (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psconv.c b/Source/ThirdParty/FreeType/src/psaux/psconv.c index fdaca7fb5d..b092482194 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psconv.c +++ b/Source/ThirdParty/FreeType/src/psaux/psconv.c @@ -4,7 +4,7 @@ /* */ /* Some convenience conversions (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psconv.h b/Source/ThirdParty/FreeType/src/psaux/psconv.h index 062de36413..cab254ac5a 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psconv.h +++ b/Source/ThirdParty/FreeType/src/psaux/psconv.h @@ -4,7 +4,7 @@ /* */ /* Some convenience conversions (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/psobjs.c b/Source/ThirdParty/FreeType/src/psaux/psobjs.c index 6e528d407f..f04edea411 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psobjs.c +++ b/Source/ThirdParty/FreeType/src/psaux/psobjs.c @@ -4,7 +4,7 @@ /* */ /* Auxiliary functions for PostScript fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -1551,7 +1551,7 @@ builder->current = &loader->current.outline; FT_GlyphLoader_Rewind( loader ); - builder->hints_globals = size->internal; + builder->hints_globals = size->internal->module_data; builder->hints_funcs = NULL; if ( hinting ) @@ -1718,6 +1718,14 @@ first = outline->n_contours <= 1 ? 0 : outline->contours[outline->n_contours - 2] + 1; + /* in malformed fonts it can happen that a contour was started */ + /* but no points were added */ + if ( outline->n_contours && first == outline->n_points ) + { + outline->n_contours--; + return; + } + /* We must not include the last point in the path if it */ /* is located on the first point. */ if ( outline->n_points > 1 ) diff --git a/Source/ThirdParty/FreeType/src/psaux/psobjs.h b/Source/ThirdParty/FreeType/src/psaux/psobjs.h index 4c7178e79f..202e5b2416 100644 --- a/Source/ThirdParty/FreeType/src/psaux/psobjs.h +++ b/Source/ThirdParty/FreeType/src/psaux/psobjs.h @@ -4,7 +4,7 @@ /* */ /* Auxiliary functions for PostScript fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/t1cmap.c b/Source/ThirdParty/FreeType/src/psaux/t1cmap.c index 7b289b7f54..45b713eb7b 100644 --- a/Source/ThirdParty/FreeType/src/psaux/t1cmap.c +++ b/Source/ThirdParty/FreeType/src/psaux/t1cmap.c @@ -4,7 +4,7 @@ /* */ /* Type 1 character map support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/t1cmap.h b/Source/ThirdParty/FreeType/src/psaux/t1cmap.h index 5e1277dc63..7870245a3a 100644 --- a/Source/ThirdParty/FreeType/src/psaux/t1cmap.h +++ b/Source/ThirdParty/FreeType/src/psaux/t1cmap.h @@ -4,7 +4,7 @@ /* */ /* Type 1 character map support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psaux/t1decode.c b/Source/ThirdParty/FreeType/src/psaux/t1decode.c index 1cd9d730a4..7dd45135de 100644 --- a/Source/ThirdParty/FreeType/src/psaux/t1decode.c +++ b/Source/ThirdParty/FreeType/src/psaux/t1decode.c @@ -4,7 +4,7 @@ /* */ /* PostScript Type 1 decoding routines (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -666,9 +666,9 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( large_int ) - FT_TRACE4(( " %ld", value )); + FT_TRACE4(( " %d", value )); else - FT_TRACE4(( " %ld", value / 65536 )); + FT_TRACE4(( " %d", value / 65536 )); #endif *top++ = value; @@ -780,10 +780,19 @@ /* point without adding any point to the outline */ idx = decoder->num_flex_vectors++; if ( idx > 0 && idx < 7 ) + { + /* in malformed fonts it is possible to have other */ + /* opcodes in the middle of a flex (which don't */ + /* increase `num_flex_vectors'); we thus have to */ + /* check whether we can add a point */ + if ( FT_SET_ERROR( t1_builder_check_points( builder, 1 ) ) ) + goto Syntax_Error; + t1_builder_add_point( builder, x, y, (FT_Byte)( idx == 3 || idx == 6 ) ); + } } break; diff --git a/Source/ThirdParty/FreeType/src/psaux/t1decode.h b/Source/ThirdParty/FreeType/src/psaux/t1decode.h index 0f5adfa156..12c27de775 100644 --- a/Source/ThirdParty/FreeType/src/psaux/t1decode.h +++ b/Source/ThirdParty/FreeType/src/psaux/t1decode.h @@ -4,7 +4,7 @@ /* */ /* PostScript Type 1 decoding routines (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshalgo.c b/Source/ThirdParty/FreeType/src/pshinter/pshalgo.c index 5a538e27d5..9ad1a3a02a 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshalgo.c +++ b/Source/ThirdParty/FreeType/src/pshinter/pshalgo.c @@ -4,7 +4,7 @@ /* */ /* PostScript hinting algorithm (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshalgo.h b/Source/ThirdParty/FreeType/src/pshinter/pshalgo.h index f1bda65013..62e97d152b 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshalgo.h +++ b/Source/ThirdParty/FreeType/src/pshinter/pshalgo.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinting algorithm (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshglob.c b/Source/ThirdParty/FreeType/src/pshinter/pshglob.c index 2ac5ef1558..c68770c73a 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshglob.c +++ b/Source/ThirdParty/FreeType/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ /* PostScript hinter global hinting management (body). */ /* Inspired by the new auto-hinter module. */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshglob.h b/Source/ThirdParty/FreeType/src/pshinter/pshglob.h index 45c957b6ef..8801cbada4 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshglob.h +++ b/Source/ThirdParty/FreeType/src/pshinter/pshglob.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinter global hinting management. */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshinter.c b/Source/ThirdParty/FreeType/src/pshinter/pshinter.c index 614e0bb3d8..13e07e1485 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshinter.c +++ b/Source/ThirdParty/FreeType/src/pshinter/pshinter.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript Hinting module */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,13 +17,13 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "pshpic.c" -#include "pshrec.c" -#include "pshglob.c" + #include "pshalgo.c" +#include "pshglob.c" #include "pshmod.c" +#include "pshpic.c" +#include "pshrec.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshmod.c b/Source/ThirdParty/FreeType/src/pshinter/pshmod.c index d5d53ab2d1..860dc0ae82 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshmod.c +++ b/Source/ThirdParty/FreeType/src/pshinter/pshmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hinter module implementation (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshmod.h b/Source/ThirdParty/FreeType/src/pshinter/pshmod.h index 39112a9561..1d2b40fa13 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshmod.h +++ b/Source/ThirdParty/FreeType/src/pshinter/pshmod.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinter module interface (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshnterr.h b/Source/ThirdParty/FreeType/src/pshinter/pshnterr.h index 7a94588b87..73d144e34c 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshnterr.h +++ b/Source/ThirdParty/FreeType/src/pshinter/pshnterr.h @@ -4,7 +4,7 @@ /* */ /* PS Hinter error codes (specification only). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshpic.c b/Source/ThirdParty/FreeType/src/pshinter/pshpic.c index d0a3d8ebc9..c0d3a64f29 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshpic.c +++ b/Source/ThirdParty/FreeType/src/pshinter/pshpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for pshinter module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshpic.h b/Source/ThirdParty/FreeType/src/pshinter/pshpic.h index 75ee573544..8d9a01c9c5 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshpic.h +++ b/Source/ThirdParty/FreeType/src/pshinter/pshpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for pshinter module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshrec.c b/Source/ThirdParty/FreeType/src/pshinter/pshrec.c index 3aeb2651fb..fff6d34250 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshrec.c +++ b/Source/ThirdParty/FreeType/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hints recorder (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/pshinter/pshrec.h b/Source/ThirdParty/FreeType/src/pshinter/pshrec.h index 97e6f0ed51..e10bc2b120 100644 --- a/Source/ThirdParty/FreeType/src/pshinter/pshrec.h +++ b/Source/ThirdParty/FreeType/src/pshinter/pshrec.h @@ -4,7 +4,7 @@ /* */ /* Postscript (Type1/Type2) hints recorder (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psnames/psmodule.c b/Source/ThirdParty/FreeType/src/psnames/psmodule.c index 01b85c3c8e..3ff8cb911b 100644 --- a/Source/ThirdParty/FreeType/src/psnames/psmodule.c +++ b/Source/ThirdParty/FreeType/src/psnames/psmodule.c @@ -4,7 +4,7 @@ /* */ /* PSNames module implementation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,6 +23,7 @@ #include "psmodule.h" +#include "pstables.h" #define DEFINE_PS_TABLES #include "pstables.h" diff --git a/Source/ThirdParty/FreeType/src/psnames/psmodule.h b/Source/ThirdParty/FreeType/src/psnames/psmodule.h index ee3c6cb631..6983b79234 100644 --- a/Source/ThirdParty/FreeType/src/psnames/psmodule.h +++ b/Source/ThirdParty/FreeType/src/psnames/psmodule.h @@ -4,7 +4,7 @@ /* */ /* High-level PSNames module interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psnames/psnamerr.h b/Source/ThirdParty/FreeType/src/psnames/psnamerr.h index 3a9f65323b..f90bf5ea43 100644 --- a/Source/ThirdParty/FreeType/src/psnames/psnamerr.h +++ b/Source/ThirdParty/FreeType/src/psnames/psnamerr.h @@ -4,7 +4,7 @@ /* */ /* PS names module error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psnames/psnames.c b/Source/ThirdParty/FreeType/src/psnames/psnames.c index e7b2c0b5ef..22466d6230 100644 --- a/Source/ThirdParty/FreeType/src/psnames/psnames.c +++ b/Source/ThirdParty/FreeType/src/psnames/psnames.c @@ -4,7 +4,7 @@ /* */ /* FreeType PSNames module component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,10 +17,10 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "pspic.c" + #include "psmodule.c" +#include "pspic.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/psnames/pspic.c b/Source/ThirdParty/FreeType/src/psnames/pspic.c index a78ec5aa81..8b9003439b 100644 --- a/Source/ThirdParty/FreeType/src/psnames/pspic.c +++ b/Source/ThirdParty/FreeType/src/psnames/pspic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for psnames module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psnames/pspic.h b/Source/ThirdParty/FreeType/src/psnames/pspic.h index 48348765cf..14497e73fa 100644 --- a/Source/ThirdParty/FreeType/src/psnames/pspic.h +++ b/Source/ThirdParty/FreeType/src/psnames/pspic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for psnames module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/psnames/pstables.h b/Source/ThirdParty/FreeType/src/psnames/pstables.h index 309f16bd3f..e0f5e30804 100644 --- a/Source/ThirdParty/FreeType/src/psnames/pstables.h +++ b/Source/ThirdParty/FreeType/src/psnames/pstables.h @@ -4,7 +4,7 @@ /* */ /* PostScript glyph names. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -4135,6 +4135,7 @@ ; +#ifdef DEFINE_PS_TABLES /* * This function searches the compressed table efficiently. */ @@ -4229,6 +4230,7 @@ NotFound: return 0; } +#endif /* DEFINE_PS_TABLES */ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ diff --git a/Source/ThirdParty/FreeType/src/raster/ftmisc.h b/Source/ThirdParty/FreeType/src/raster/ftmisc.h index 981ce32279..d1e6627ab4 100644 --- a/Source/ThirdParty/FreeType/src/raster/ftmisc.h +++ b/Source/ThirdParty/FreeType/src/raster/ftmisc.h @@ -5,7 +5,7 @@ /* Miscellaneous macros for stand-alone rasterizer (specification */ /* only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/Source/ThirdParty/FreeType/src/raster/ftraster.c b/Source/ThirdParty/FreeType/src/raster/ftraster.c index 429f0d2509..c5643f6334 100644 --- a/Source/ThirdParty/FreeType/src/raster/ftraster.c +++ b/Source/ThirdParty/FreeType/src/raster/ftraster.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/raster/ftraster.h b/Source/ThirdParty/FreeType/src/raster/ftraster.h index 65cd5f9609..6b3050cb3d 100644 --- a/Source/ThirdParty/FreeType/src/raster/ftraster.h +++ b/Source/ThirdParty/FreeType/src/raster/ftraster.h @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/Source/ThirdParty/FreeType/src/raster/ftrend1.c b/Source/ThirdParty/FreeType/src/raster/ftrend1.c index 5bd4b30c8b..1a83e9e477 100644 --- a/Source/ThirdParty/FreeType/src/raster/ftrend1.c +++ b/Source/ThirdParty/FreeType/src/raster/ftrend1.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/raster/ftrend1.h b/Source/ThirdParty/FreeType/src/raster/ftrend1.h index a431f185d2..cff702d140 100644 --- a/Source/ThirdParty/FreeType/src/raster/ftrend1.h +++ b/Source/ThirdParty/FreeType/src/raster/ftrend1.h @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/raster/raster.c b/Source/ThirdParty/FreeType/src/raster/raster.c index 5b21dcbc6a..46a6690b17 100644 --- a/Source/ThirdParty/FreeType/src/raster/raster.c +++ b/Source/ThirdParty/FreeType/src/raster/raster.c @@ -4,7 +4,7 @@ /* */ /* FreeType monochrome rasterer module component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,11 +17,11 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "rastpic.c" + #include "ftraster.c" #include "ftrend1.c" +#include "rastpic.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/raster/rasterrs.h b/Source/ThirdParty/FreeType/src/raster/rasterrs.h index 44da7fca56..0d646908ad 100644 --- a/Source/ThirdParty/FreeType/src/raster/rasterrs.h +++ b/Source/ThirdParty/FreeType/src/raster/rasterrs.h @@ -4,7 +4,7 @@ /* */ /* monochrome renderer error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/raster/rastpic.c b/Source/ThirdParty/FreeType/src/raster/rastpic.c index dcfa92eef7..7085339b7b 100644 --- a/Source/ThirdParty/FreeType/src/raster/rastpic.c +++ b/Source/ThirdParty/FreeType/src/raster/rastpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for raster module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/raster/rastpic.h b/Source/ThirdParty/FreeType/src/raster/rastpic.h index 7815876383..dcd691310d 100644 --- a/Source/ThirdParty/FreeType/src/raster/rastpic.h +++ b/Source/ThirdParty/FreeType/src/raster/rastpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for raster module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/pngshim.c b/Source/ThirdParty/FreeType/src/sfnt/pngshim.c index ff6729273f..b9b296ea5f 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/pngshim.c +++ b/Source/ThirdParty/FreeType/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ /* */ /* PNG Bitmap glyph support. */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* Google, Inc. */ /* Written by Stuart Gill and Behdad Esfahbod. */ /* */ @@ -24,9 +24,10 @@ #include FT_CONFIG_STANDARD_LIBRARY_H -#ifdef FT_CONFIG_OPTION_USE_PNG +#if defined( TT_CONFIG_OPTION_EMBEDDED_BITMAPS ) && \ + defined( FT_CONFIG_OPTION_USE_PNG ) - /* We always include <stjmp.h>, so make libpng shut up! */ + /* We always include <setjmp.h>, so make libpng shut up! */ #define PNG_SKIP_SETJMP_CHECK 1 #include <png.h> #include "pngshim.h" @@ -377,7 +378,12 @@ return error; } -#endif /* FT_CONFIG_OPTION_USE_PNG */ +#else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ + + /* ANSI C doesn't like empty source files */ + typedef int _pngshim_dummy; + +#endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* END */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/pngshim.h b/Source/ThirdParty/FreeType/src/sfnt/pngshim.h index 0af4bfc5b4..344eceac12 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/pngshim.h +++ b/Source/ThirdParty/FreeType/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ /* */ /* PNG Bitmap glyph support. */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2017 by */ /* Google, Inc. */ /* Written by Stuart Gill and Behdad Esfahbod. */ /* */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfdriver.c b/Source/ThirdParty/FreeType/src/sfnt/sfdriver.c index 1f15223cb5..991433ee4c 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfdriver.c +++ b/Source/ThirdParty/FreeType/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,7 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_SFNT_H #include FT_INTERNAL_OBJECTS_H +#include FT_TRUETYPE_IDS_H #include "sfdriver.h" #include "ttload.h" @@ -50,6 +51,11 @@ #include FT_SERVICE_SFNT_H #include FT_SERVICE_TT_CMAP_H +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#endif + /*************************************************************************/ /* */ @@ -220,113 +226,838 @@ * */ - static const char* - sfnt_get_ps_name( TT_Face face ) + /* an array representing allowed ASCII characters in a PS string */ + static const unsigned char sfnt_ps_map[16] = { - FT_Int n, found_win, found_apple; - const char* result = NULL; + /* 4 0 C 8 */ + 0x00, 0x00, /* 0x00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ + 0x00, 0x00, /* 0x10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ + 0xDE, 0x7C, /* 0x20: 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 */ + 0xFF, 0xAF, /* 0x30: 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 */ + 0xFF, 0xFF, /* 0x40: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ + 0xFF, 0xD7, /* 0x50: 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 */ + 0xFF, 0xFF, /* 0x60: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ + 0xFF, 0x57 /* 0x70: 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 */ + }; + + + static int + sfnt_is_postscript( int c ) + { + unsigned int cc; - /* shouldn't happen, but just in case to avoid memory leaks */ - if ( face->postscript_name ) - return face->postscript_name; + if ( c < 0 || c >= 0x80 ) + return 0; - /* scan the name table to see whether we have a Postscript name here, */ - /* either in Macintosh or Windows platform encodings */ - found_win = -1; - found_apple = -1; + cc = (unsigned int)c; + + return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) ); + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /* Only ASCII letters and digits are taken for a variation font */ + /* instance's PostScript name. */ + /* */ + /* `ft_isalnum' is a macro, but we need a function here, thus */ + /* this definition. */ + static int + sfnt_is_alphanumeric( int c ) + { + return ft_isalnum( c ); + } + + + /* the implementation of MurmurHash3 is taken and adapted from */ + /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */ + +#define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) ) + + + static FT_UInt32 + fmix32( FT_UInt32 h ) + { + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; + } + + + static void + murmur_hash_3_128( const void* key, + const unsigned int len, + FT_UInt32 seed, + void* out ) + { + const FT_Byte* data = (const FT_Byte*)key; + const int nblocks = (int)len / 16; + + FT_UInt32 h1 = seed; + FT_UInt32 h2 = seed; + FT_UInt32 h3 = seed; + FT_UInt32 h4 = seed; + + const FT_UInt32 c1 = 0x239b961b; + const FT_UInt32 c2 = 0xab0e9789; + const FT_UInt32 c3 = 0x38b34ae5; + const FT_UInt32 c4 = 0xa1e38b93; + + const FT_UInt32* blocks = (const FT_UInt32*)( data + nblocks * 16 ); + + int i; + + + for( i = -nblocks; i; i++ ) + { + FT_UInt32 k1 = blocks[i * 4 + 0]; + FT_UInt32 k2 = blocks[i * 4 + 1]; + FT_UInt32 k3 = blocks[i * 4 + 2]; + FT_UInt32 k4 = blocks[i * 4 + 3]; + + + k1 *= c1; + k1 = ROTL32( k1, 15 ); + k1 *= c2; + h1 ^= k1; + + h1 = ROTL32( h1, 19 ); + h1 += h2; + h1 = h1 * 5 + 0x561ccd1b; + + k2 *= c2; + k2 = ROTL32( k2, 16 ); + k2 *= c3; + h2 ^= k2; + + h2 = ROTL32( h2, 17 ); + h2 += h3; + h2 = h2 * 5 + 0x0bcaa747; + + k3 *= c3; + k3 = ROTL32( k3, 17 ); + k3 *= c4; + h3 ^= k3; + + h3 = ROTL32( h3, 15 ); + h3 += h4; + h3 = h3 * 5 + 0x96cd1c35; + + k4 *= c4; + k4 = ROTL32( k4, 18 ); + k4 *= c1; + h4 ^= k4; + + h4 = ROTL32( h4, 13 ); + h4 += h1; + h4 = h4 * 5 + 0x32ac3b17; + } - for ( n = 0; n < face->num_names; n++ ) { - TT_NameEntryRec* name = face->name_table.names + n; + const FT_Byte* tail = (const FT_Byte*)( data + nblocks * 16 ); + FT_UInt32 k1 = 0; + FT_UInt32 k2 = 0; + FT_UInt32 k3 = 0; + FT_UInt32 k4 = 0; - if ( name->nameID == 6 && name->stringLength > 0 ) + + switch ( len & 15 ) { - if ( name->platformID == 3 && - name->encodingID == 1 && - name->languageID == 0x409 ) - found_win = n; - - if ( name->platformID == 1 && - name->encodingID == 0 && - name->languageID == 0 ) - found_apple = n; + case 15: + k4 ^= (FT_UInt32)tail[14] << 16; + case 14: + k4 ^= (FT_UInt32)tail[13] << 8; + case 13: + k4 ^= (FT_UInt32)tail[12]; + k4 *= c4; + k4 = ROTL32( k4, 18 ); + k4 *= c1; + h4 ^= k4; + + case 12: + k3 ^= (FT_UInt32)tail[11] << 24; + case 11: + k3 ^= (FT_UInt32)tail[10] << 16; + case 10: + k3 ^= (FT_UInt32)tail[9] << 8; + case 9: + k3 ^= (FT_UInt32)tail[8]; + k3 *= c3; + k3 = ROTL32( k3, 17 ); + k3 *= c4; + h3 ^= k3; + + case 8: + k2 ^= (FT_UInt32)tail[7] << 24; + case 7: + k2 ^= (FT_UInt32)tail[6] << 16; + case 6: + k2 ^= (FT_UInt32)tail[5] << 8; + case 5: + k2 ^= (FT_UInt32)tail[4]; + k2 *= c2; + k2 = ROTL32( k2, 16 ); + k2 *= c3; + h2 ^= k2; + + case 4: + k1 ^= (FT_UInt32)tail[3] << 24; + case 3: + k1 ^= (FT_UInt32)tail[2] << 16; + case 2: + k1 ^= (FT_UInt32)tail[1] << 8; + case 1: + k1 ^= (FT_UInt32)tail[0]; + k1 *= c1; + k1 = ROTL32( k1, 15 ); + k1 *= c2; + h1 ^= k1; } } - if ( found_win != -1 ) + h1 ^= len; + h2 ^= len; + h3 ^= len; + h4 ^= len; + + h1 += h2; + h1 += h3; + h1 += h4; + + h2 += h1; + h3 += h1; + h4 += h1; + + h1 = fmix32( h1 ); + h2 = fmix32( h2 ); + h3 = fmix32( h3 ); + h4 = fmix32( h4 ); + + h1 += h2; + h1 += h3; + h1 += h4; + + h2 += h1; + h3 += h1; + h4 += h1; + + ((FT_UInt32*)out)[0] = h1; + ((FT_UInt32*)out)[1] = h2; + ((FT_UInt32*)out)[2] = h3; + ((FT_UInt32*)out)[3] = h4; + } + + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + typedef int (*char_type_func)( int c ); + + + /* handling of PID/EID 3/0 and 3/1 is the same */ +#define IS_WIN( n ) ( (n)->platformID == 3 && \ + ( (n)->encodingID == 1 || (n)->encodingID == 0 ) && \ + (n)->languageID == 0x409 ) + +#define IS_APPLE( n ) ( (n)->platformID == 1 && \ + (n)->encodingID == 0 && \ + (n)->languageID == 0 ) + + static char* + get_win_string( FT_Memory memory, + FT_Stream stream, + TT_Name entry, + char_type_func char_type, + FT_Bool report_invalid_characters ) + { + FT_Error error = FT_Err_Ok; + + char* result = NULL; + FT_String* r; + FT_Char* p; + FT_UInt len; + + FT_UNUSED( error ); + + + if ( FT_ALLOC( result, entry->stringLength / 2 + 1 ) ) + return NULL; + + if ( FT_STREAM_SEEK( entry->stringOffset ) || + FT_FRAME_ENTER( entry->stringLength ) ) { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_win; - FT_UInt len = name->stringLength / 2; - FT_Error error = FT_Err_Ok; + FT_FREE( result ); + entry->stringLength = 0; + entry->stringOffset = 0; + FT_FREE( entry->string ); - FT_UNUSED( error ); + return NULL; + } + r = (FT_String*)result; + p = (FT_Char*)stream->cursor; - if ( !FT_ALLOC( result, name->stringLength + 1 ) ) + for ( len = entry->stringLength / 2; len > 0; len--, p += 2 ) + { + if ( p[0] == 0 ) { - FT_Stream stream = face->name_table.stream; - FT_String* r = (FT_String*)result; - FT_Char* p; + if ( char_type( p[1] ) ) + *r++ = p[1]; + else + { + if ( report_invalid_characters ) + { + FT_TRACE0(( "get_win_string:" + " Character `%c' (0x%X) invalid in PS name string\n", + p[1], p[1] )); + /* it's not the job of FreeType to correct PS names... */ + *r++ = p[1]; + } + } + } + } + *r = '\0'; + + FT_FRAME_EXIT(); + + return result; + } + + + static char* + get_apple_string( FT_Memory memory, + FT_Stream stream, + TT_Name entry, + char_type_func char_type, + FT_Bool report_invalid_characters ) + { + FT_Error error = FT_Err_Ok; + + char* result = NULL; + FT_String* r; + FT_Char* p; + FT_UInt len; + + FT_UNUSED( error ); + + if ( FT_ALLOC( result, entry->stringLength + 1 ) ) + return NULL; + + if ( FT_STREAM_SEEK( entry->stringOffset ) || + FT_FRAME_ENTER( entry->stringLength ) ) + { + FT_FREE( result ); + entry->stringOffset = 0; + entry->stringLength = 0; + FT_FREE( entry->string ); + + return NULL; + } - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_FRAME_ENTER( name->stringLength ) ) + r = (FT_String*)result; + p = (FT_Char*)stream->cursor; + + for ( len = entry->stringLength; len > 0; len--, p++ ) + { + if ( char_type( *p ) ) + *r++ = *p; + else + { + if ( report_invalid_characters ) { - FT_FREE( result ); - name->stringLength = 0; - name->stringOffset = 0; - FT_FREE( name->string ); + FT_TRACE0(( "get_apple_string:" + " Character `%c' (0x%X) invalid in PS name string\n", + *p, *p )); + /* it's not the job of FreeType to correct PS names... */ + *r++ = *p; + } + } + } + *r = '\0'; + + FT_FRAME_EXIT(); + + return result; + } - goto Exit; + + static FT_Bool + sfnt_get_name_id( TT_Face face, + FT_UShort id, + FT_Int *win, + FT_Int *apple ) + { + FT_Int n; + + + *win = -1; + *apple = -1; + + for ( n = 0; n < face->num_names; n++ ) + { + TT_Name name = face->name_table.names + n; + + + if ( name->nameID == id && name->stringLength > 0 ) + { + if ( IS_WIN( name ) ) + *win = n; + + if ( IS_APPLE( name ) ) + *apple = n; + } + } + + return ( *win >= 0 ) || ( *apple >= 0 ); + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /* + The maximum length of an axis value descriptor. + + We need 65536 different values for the decimal fraction; this fits + nicely into five decimal places. Consequently, it consists of + + . the minus sign if the number is negative, + . up to five characters for the digits before the decimal point, + . the decimal point if there is a fractional part, and + . up to five characters for the digits after the decimal point. + + We also need one byte for the leading `_' character and up to four + bytes for the axis tag. + */ +#define MAX_VALUE_DESCRIPTOR_LEN ( 1 + 5 + 1 + 5 + 1 + 4 ) + + + /* the maximum length of PostScript font names */ +#define MAX_PS_NAME_LEN 127 + + + /* + * Find the shortest decimal representation of a 16.16 fixed point + * number. The function fills `buf' with the result, returning a pointer + * to the position after the representation's last byte. + */ + + static char* + fixed2float( FT_Int fixed, + char* buf ) + { + char* p; + char* q; + char tmp[5]; + + FT_Int int_part; + FT_Int frac_part; + + FT_Int i; + + + p = buf; + + if ( fixed == 0 ) + { + *p++ = '0'; + return p; + } + + if ( fixed < 0 ) + { + *p++ = '-'; + fixed = -fixed; + } + + int_part = ( fixed >> 16 ) & 0xFFFF; + frac_part = fixed & 0xFFFF; + + /* get digits of integer part (in reverse order) */ + q = tmp; + while ( int_part > 0 ) + { + *q++ = '0' + int_part % 10; + int_part /= 10; + } + + /* copy digits in correct order to buffer */ + while ( q > tmp ) + *p++ = *--q; + + if ( !frac_part ) + return p; + + /* save position of point */ + q = p; + *p++ = '.'; + + /* apply rounding */ + frac_part = frac_part * 10 + 5; + + /* get digits of fractional part */ + for ( i = 0; i < 5; i++ ) + { + *p++ = '0' + (char)( frac_part / 0x10000L ); + + frac_part %= 0x10000L; + if ( !frac_part ) + break; + + frac_part *= 10; + } + + /* + If the remainder stored in `frac_part' (after the last FOR loop) is + smaller than 34480*10, the resulting decimal value minus 0.00001 is + an equivalent representation of `fixed'. + + The above FOR loop always finds the larger of the two values; I + verified this by iterating over all possible fixed point numbers. + + If the remainder is 17232*10, both values are equally good, and we + take the next even number (following IEEE 754's `round to nearest, + ties to even' rounding rule). + + If the remainder is smaller than 17232*10, the lower of the two + numbers is nearer to the exact result (values 17232 and 34480 were + also found by testing all possible fixed point values). + + We use this to find a shorter decimal representation. If not ending + with digit zero, we take the representation with less error. + */ + p--; + if ( p - q == 5 ) /* five digits? */ + { + /* take the representation that has zero as the last digit */ + if ( frac_part < 34480 * 10 && + *p == '1' ) + *p = '0'; + + /* otherwise use the one with less error */ + else if ( frac_part == 17232 * 10 && + *p & 1 ) + *p -= 1; + + else if ( frac_part < 17232 * 10 && + *p != '0' ) + *p -= 1; + } + + /* remove trailing zeros */ + while ( *p == '0' ) + *p-- = '\0'; + + return p + 1; + } + + + static const char hexdigits[16] = + { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + + static const char* + sfnt_get_var_ps_name( TT_Face face ) + { + FT_Error error; + FT_Memory memory = face->root.memory; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + FT_UInt num_coords; + FT_Fixed* coords; + FT_MM_Var* mm_var; + + FT_Int found, win, apple; + FT_UInt i, j; + + char* result = NULL; + char* p; + + + if ( !face->var_postscript_prefix ) + { + FT_UInt len; + + + /* check whether we have a Variations PostScript Name Prefix */ + found = sfnt_get_name_id( face, + TT_NAME_ID_VARIATIONS_PREFIX, + &win, + &apple ); + if ( !found ) + { + /* otherwise use the typographic family name */ + found = sfnt_get_name_id( face, + TT_NAME_ID_TYPOGRAPHIC_FAMILY, + &win, + &apple ); + } + + if ( !found ) + { + /* as a last resort we try the family name; note that this is */ + /* not in the Adobe TechNote, but GX fonts (which predate the */ + /* TechNote) benefit from this behaviour */ + found = sfnt_get_name_id( face, + TT_NAME_ID_FONT_FAMILY, + &win, + &apple ); + } + + if ( !found ) + { + FT_TRACE0(( "sfnt_get_var_ps_name:" + " Can't construct PS name prefix for font instances\n" )); + return NULL; + } + + /* prefer Windows entries over Apple */ + if ( win != -1 ) + result = get_win_string( face->root.memory, + face->name_table.stream, + face->name_table.names + win, + sfnt_is_alphanumeric, + 0 ); + else + result = get_apple_string( face->root.memory, + face->name_table.stream, + face->name_table.names + apple, + sfnt_is_alphanumeric, + 0 ); + + len = ft_strlen( result ); + + /* sanitize if necessary; we reserve space for 36 bytes (a 128bit */ + /* checksum as a hex number, preceded by `-' and followed by three */ + /* ASCII dots, to be used if the constructed PS name would be too */ + /* long); this is also sufficient for a single instance */ + if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) ) + { + len = MAX_PS_NAME_LEN - ( 1 + 32 + 3 ); + result[len] = '\0'; + + FT_TRACE0(( "sfnt_get_var_ps_name:" + " Shortening variation PS name prefix\n" + " " + " to %d characters\n", len )); + } + + face->var_postscript_prefix = result; + face->var_postscript_prefix_len = len; + } + + mm->get_var_blend( FT_FACE( face ), + &num_coords, + &coords, + NULL, + &mm_var ); + + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_Long instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1; + FT_UInt psid = mm_var->namedstyle[instance].psid; + + char* ps_name = NULL; + + + /* try first to load the name string with index `postScriptNameID' */ + if ( psid == 6 || + ( psid > 255 && psid < 32768 ) ) + (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name ); + + if ( ps_name ) + { + result = ps_name; + p = result + ft_strlen( result ) + 1; + + goto check_length; + } + else + { + /* otherwise construct a name using `subfamilyNameID' */ + FT_UInt strid = mm_var->namedstyle[instance].strid; + + char* subfamily_name; + char* s; + + + (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name ); + + if ( !subfamily_name ) + { + FT_TRACE1(( "sfnt_get_var_ps_name:" + " can't construct named instance PS name;\n" + " " + " trying to construct normal instance PS name\n" )); + goto construct_instance_name; } - p = (FT_Char*)stream->cursor; + /* after the prefix we have character `-' followed by the */ + /* subfamily name (using only characters a-z, A-Z, and 0-9) */ + if ( FT_ALLOC( result, face->var_postscript_prefix_len + + 1 + ft_strlen( subfamily_name ) + 1 ) ) + return NULL; + + ft_strcpy( result, face->var_postscript_prefix ); + + p = result + face->var_postscript_prefix_len; + *p++ = '-'; - for ( ; len > 0; len--, p += 2 ) + s = subfamily_name; + while ( *s ) { - if ( p[0] == 0 && p[1] >= 32 ) - *r++ = p[1]; + if ( ft_isalnum( *s ) ) + *p++ = *s; + s++; } - *r = '\0'; + *p++ = '\0'; + + FT_FREE( subfamily_name ); + } + } + else + { + FT_Var_Axis* axis; + + + construct_instance_name: + axis = mm_var->axis; - FT_FRAME_EXIT(); + if ( FT_ALLOC( result, + face->var_postscript_prefix_len + + num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) ) + return NULL; + + p = result; + + ft_strcpy( p, face->var_postscript_prefix ); + p += face->var_postscript_prefix_len; + + for ( i = 0; i < num_coords; i++, coords++, axis++ ) + { + char t; + + + /* omit axis value descriptor if it is identical */ + /* to the default axis value */ + if ( *coords == axis->def ) + continue; + + *p++ = '_'; + p = fixed2float( *coords, p ); + + t = (char)( axis->tag >> 24 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)( axis->tag >> 16 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)( axis->tag >> 8 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)axis->tag; + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; } - goto Exit; } - if ( found_apple != -1 ) + check_length: + if ( p - result > MAX_PS_NAME_LEN ) { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_apple; - FT_UInt len = name->stringLength; - FT_Error error = FT_Err_Ok; + /* the PS name is too long; replace the part after the prefix with */ + /* a checksum; we use MurmurHash 3 with a hash length of 128 bit */ - FT_UNUSED( error ); + FT_UInt32 seed = 123456789; + FT_UInt32 hash[4]; + FT_UInt32* h; - if ( !FT_ALLOC( result, len + 1 ) ) + + murmur_hash_3_128( result, p - result, seed, hash ); + + p = result + face->var_postscript_prefix_len; + *p++ = '-'; + + /* we convert the hash value to hex digits from back to front */ + p += 32 + 3; + h = hash + 3; + + *p-- = '\0'; + *p-- = '.'; + *p-- = '.'; + *p-- = '.'; + + for ( i = 0; i < 4; i++, h-- ) { - FT_Stream stream = face->name_table.stream; + FT_UInt32 v = *h; - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_STREAM_READ( result, len ) ) + for ( j = 0; j < 8; j++ ) { - name->stringOffset = 0; - name->stringLength = 0; - FT_FREE( name->string ); - FT_FREE( result ); - goto Exit; + *p-- = hexdigits[v & 0xF]; + v >>= 4; } - ((char*)result)[len] = '\0'; } } - Exit: + return result; + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + static const char* + sfnt_get_ps_name( TT_Face face ) + { + FT_Int found, win, apple; + const char* result = NULL; + + + if ( face->postscript_name ) + return face->postscript_name; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( face->blend ) + { + face->postscript_name = sfnt_get_var_ps_name( face ); + return face->postscript_name; + } +#endif + + /* scan the name table to see whether we have a Postscript name here, */ + /* either in Macintosh or Windows platform encodings */ + found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + if ( !found ) + return NULL; + + /* prefer Windows entries over Apple */ + if ( win != -1 ) + result = get_win_string( face->root.memory, + face->name_table.stream, + face->name_table.names + win, + sfnt_is_postscript, + 1 ); + else + result = get_apple_string( face->root.memory, + face->name_table.stream, + face->name_table.names + apple, + sfnt_is_postscript, + 1 ); + face->postscript_name = result; + return result; } @@ -528,7 +1259,8 @@ tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ - tt_face_get_name /* TT_Get_Name_Func get_name */ + tt_face_get_name, /* TT_Get_Name_Func get_name */ + sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ ) diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfdriver.h b/Source/ThirdParty/FreeType/src/sfnt/sfdriver.h index 2694488e20..38710b60f2 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfdriver.h +++ b/Source/ThirdParty/FreeType/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/sferrors.h b/Source/ThirdParty/FreeType/src/sfnt/sferrors.h index c2f9fdfead..3cf73d725d 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sferrors.h +++ b/Source/ThirdParty/FreeType/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ /* */ /* SFNT error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfnt.c b/Source/ThirdParty/FreeType/src/sfnt/sfnt.c index 952d6d425a..6cf8c9ef30 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfnt.c +++ b/Source/ThirdParty/FreeType/src/sfnt/sfnt.c @@ -4,7 +4,7 @@ /* */ /* Single object library component. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,27 +17,19 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> + +#include "pngshim.c" +#include "sfdriver.c" #include "sfntpic.c" -#include "ttload.c" -#include "ttmtx.c" +#include "sfobjs.c" +#include "ttbdf.c" #include "ttcmap.c" #include "ttkern.c" -#include "sfobjs.c" -#include "sfdriver.c" - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#include "pngshim.c" -#include "ttsbit.c" -#endif - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttload.c" +#include "ttmtx.c" #include "ttpost.c" -#endif +#include "ttsbit.c" -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.c" -#endif /* END */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfntpic.c b/Source/ThirdParty/FreeType/src/sfnt/sfntpic.c index 1f596c0936..8eadd601fd 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfntpic.c +++ b/Source/ThirdParty/FreeType/src/sfnt/sfntpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfntpic.h b/Source/ThirdParty/FreeType/src/sfnt/sfntpic.h index 5ce96d3938..3afb668db0 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfntpic.h +++ b/Source/ThirdParty/FreeType/src/sfnt/sfntpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfobjs.c b/Source/ThirdParty/FreeType/src/sfnt/sfobjs.c index 818009ef58..ac2e620e5d 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfobjs.c +++ b/Source/ThirdParty/FreeType/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ /* */ /* SFNT object management (base). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -54,8 +54,8 @@ /* convert a UTF-16 name entry to ASCII */ static FT_String* - tt_name_entry_ascii_from_utf16( TT_NameEntry entry, - FT_Memory memory ) + tt_name_ascii_from_utf16( TT_Name entry, + FT_Memory memory ) { FT_String* string = NULL; FT_UInt len, code, n; @@ -89,8 +89,8 @@ /* convert an Apple Roman or symbol name entry to ASCII */ static FT_String* - tt_name_entry_ascii_from_other( TT_NameEntry entry, - FT_Memory memory ) + tt_name_ascii_from_other( TT_Name entry, + FT_Memory memory ) { FT_String* string = NULL; FT_UInt len, code, n; @@ -122,8 +122,8 @@ } - typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, - FT_Memory memory ); + typedef FT_String* (*TT_Name_ConvertFunc)( TT_Name entry, + FT_Memory memory ); /* documentation is in sfnt.h */ @@ -133,20 +133,21 @@ FT_UShort nameid, FT_String** name ) { - FT_Memory memory = face->root.memory; - FT_Error error = FT_Err_Ok; - FT_String* result = NULL; - FT_UShort n; - TT_NameEntryRec* rec; - FT_Int found_apple = -1; - FT_Int found_apple_roman = -1; - FT_Int found_apple_english = -1; - FT_Int found_win = -1; - FT_Int found_unicode = -1; + FT_Memory memory = face->root.memory; + FT_Error error = FT_Err_Ok; + FT_String* result = NULL; + FT_UShort n; + TT_Name rec; - FT_Bool is_english = 0; + FT_Int found_apple = -1; + FT_Int found_apple_roman = -1; + FT_Int found_apple_english = -1; + FT_Int found_win = -1; + FT_Int found_unicode = -1; - TT_NameEntry_ConvertFunc convert; + FT_Bool is_english = 0; + + TT_Name_ConvertFunc convert; FT_ASSERT( name ); @@ -231,7 +232,7 @@ /* all Unicode strings are encoded using UTF-16BE */ case TT_MS_ID_UNICODE_CS: case TT_MS_ID_SYMBOL_CS: - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; break; case TT_MS_ID_UCS_4: @@ -240,7 +241,7 @@ /* MsGothic font shipped with Windows Vista shows that this really */ /* means UTF-16 encoded names (UCS-4 values are only used within */ /* charmaps). */ - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; break; default: @@ -250,12 +251,12 @@ else if ( found_apple >= 0 ) { rec = face->name_table.names + found_apple; - convert = tt_name_entry_ascii_from_other; + convert = tt_name_ascii_from_other; } else if ( found_unicode >= 0 ) { rec = face->name_table.names + found_unicode; - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; } if ( rec && convert ) @@ -310,7 +311,7 @@ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_PRC, FT_ENCODING_PRC }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } @@ -893,7 +894,17 @@ 0 ); } - FT_FACE_FIND_GLOBAL_SERVICE( face, face->var, METRICS_VARIATIONS ); + if ( !face->var ) + { + /* we want the metrics variations interface */ + /* from the `truetype' module only */ + FT_Module tt_module = FT_Get_Module( library, "truetype" ); + + + face->var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); + } #endif FT_TRACE2(( "SFNT driver\n" )); @@ -909,6 +920,10 @@ face_index = FT_ABS( face_instance_index ) & 0xFFFF; + /* value -(N+1) requests information on index N */ + if ( face_instance_index < 0 ) + face_index--; + if ( face_index >= face->ttc_header.count ) { if ( face_instance_index >= 0 ) @@ -927,6 +942,8 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { + FT_Memory memory = face->root.memory; + FT_ULong fvar_len; FT_ULong version; @@ -939,6 +956,9 @@ FT_Int instance_index; + FT_Byte* default_values = NULL; + FT_Byte* instance_values = NULL; + face->is_default_instance = 1; @@ -949,7 +969,7 @@ fvar_len < 20 || FT_READ_ULONG( version ) || FT_READ_USHORT( offset ) || - FT_STREAM_SKIP( 2 ) /* count_size_pairs */ || + FT_STREAM_SKIP( 2 ) /* reserved */ || FT_READ_USHORT( num_axes ) || FT_READ_USHORT( axis_size ) || FT_READ_USHORT( num_instances ) || @@ -965,18 +985,13 @@ /* check that the data is bound by the table length */ if ( version != 0x00010000UL || -#if 0 - /* fonts like `JamRegular.ttf' have an incorrect value for */ - /* `count_size_pairs'; since value 2 is hard-coded in `fvar' */ - /* version 1.0, we simply ignore it */ - count_size_pairs != 2 || -#endif axis_size != 20 || num_axes == 0 || /* `num_axes' limit implied by 16-bit `instance_size' */ num_axes > 0x3FFE || !( instance_size == 4 + 4 * num_axes || instance_size == 6 + 4 * num_axes ) || + /* `num_instances' limit implied by limited range of name IDs */ num_instances > 0x7EFF || offset + axis_size * num_axes + @@ -985,19 +1000,73 @@ else face->variation_support |= TT_FACE_FLAG_VAR_FVAR; - /* we don't support Multiple Master CFFs yet */ - if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) ) - num_instances = 0; + /* + * As documented in the OpenType specification, an entry for the + * default instance may be omitted in the named instance table. In + * particular this means that even if there is no named instance + * table in the font we actually do have a named instance, namely the + * default instance. + * + * For consistency, we always want the default instance in our list + * of named instances. If it is missing, we try to synthesize it + * later on. Here, we have to adjust `num_instances' accordingly. + */ - /* we support at most 2^15 - 1 instances */ - if ( num_instances >= ( 1U << 15 ) - 1 ) + if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && + !( FT_ALLOC( default_values, num_axes * 4 ) || + FT_ALLOC( instance_values, num_axes * 4 ) ) ) { - if ( face_instance_index >= 0 ) - return FT_THROW( Invalid_Argument ); - else - num_instances = 0; + /* the current stream position is 16 bytes after the table start */ + FT_ULong array_start = FT_STREAM_POS() - 16 + offset; + FT_ULong default_value_offset, instance_offset; + + FT_Byte* p; + FT_UInt i; + + + default_value_offset = array_start + 8; + p = default_values; + + for ( i = 0; i < num_axes; i++ ) + { + (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); + + default_value_offset += axis_size; + p += 4; + } + + instance_offset = array_start + axis_size * num_axes + 4; + + for ( i = 0; i < num_instances; i++ ) + { + (void)FT_STREAM_READ_AT( instance_offset, + instance_values, + num_axes * 4 ); + + if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) + break; + + instance_offset += instance_size; + } + + if ( i == num_instances ) + { + /* no default instance in named instance table; */ + /* we thus have to synthesize it */ + num_instances++; + } } + FT_FREE( default_values ); + FT_FREE( instance_values ); + + /* we don't support Multiple Master CFFs yet; */ + /* note that `glyf' or `CFF2' have precedence */ + if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && + face->goto_table( face, TTAG_CFF2, stream, 0 ) && + !face->goto_table( face, TTAG_CFF, stream, 0 ) ) + num_instances = 0; + /* instance indices in `face_instance_index' start with index 1, */ /* thus `>' and not `>=' */ if ( instance_index > num_instances ) @@ -1075,8 +1144,8 @@ FT_Bool has_outline; FT_Bool is_apple_sbit; FT_Bool is_apple_sbix; - FT_Bool ignore_preferred_family = FALSE; - FT_Bool ignore_preferred_subfamily = FALSE; + FT_Bool ignore_typographic_family = FALSE; + FT_Bool ignore_typographic_subfamily = FALSE; SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -1091,10 +1160,10 @@ for ( i = 0; i < num_params; i++ ) { - if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) - ignore_preferred_family = TRUE; - else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) - ignore_preferred_subfamily = TRUE; + if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) + ignore_typographic_family = TRUE; + else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) + ignore_typographic_subfamily = TRUE; } } @@ -1258,30 +1327,10 @@ /* embedded bitmap support */ if ( sfnt->load_eblc ) - { LOAD_( eblc ); - if ( error ) - { - /* a font which contains neither bitmaps nor outlines is */ - /* still valid (although rather useless in most cases); */ - /* however, you can find such stripped fonts in PDFs */ - if ( FT_ERR_EQ( error, Table_Missing ) ) - error = FT_Err_Ok; - else - goto Exit; - } - } + /* consider the pclt, kerning, and gasp tables as optional */ LOAD_( pclt ); - if ( error ) - { - if ( FT_ERR_NEQ( error, Table_Missing ) ) - goto Exit; - - face->pclt.Version = 0; - } - - /* consider the kerning and gasp tables as optional */ LOAD_( gasp ); LOAD_( kern ); @@ -1297,27 +1346,27 @@ face->root.style_name = NULL; if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) { - if ( !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); + if ( !ignore_typographic_family ) + GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) GET_NAME( FONT_FAMILY, &face->root.family_name ); - if ( !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); + if ( !ignore_typographic_subfamily ) + GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } else { GET_NAME( WWS_FAMILY, &face->root.family_name ); - if ( !face->root.family_name && !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); + if ( !face->root.family_name && !ignore_typographic_family ) + GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) GET_NAME( FONT_FAMILY, &face->root.family_name ); GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); - if ( !face->root.style_name && !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); + if ( !face->root.style_name && !ignore_typographic_subfamily ) + GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } @@ -1707,7 +1756,10 @@ FT_FREE( face->sbit_strike_map ); face->root.num_fixed_sizes = 0; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->postscript_name ); + FT_FREE( face->var_postscript_prefix ); +#endif face->sfnt = NULL; } diff --git a/Source/ThirdParty/FreeType/src/sfnt/sfobjs.h b/Source/ThirdParty/FreeType/src/sfnt/sfobjs.h index 60b5698edd..705381459a 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/sfobjs.h +++ b/Source/ThirdParty/FreeType/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ /* */ /* SFNT object management (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttbdf.c b/Source/ThirdParty/FreeType/src/sfnt/ttbdf.c index 62acf090c2..2196e3791e 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttbdf.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -246,7 +246,12 @@ return error; } -#endif /* TT_CONFIG_OPTION_BDF */ +#else /* !TT_CONFIG_OPTION_BDF */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_bdf_dummy; + +#endif /* !TT_CONFIG_OPTION_BDF */ /* END */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttbdf.h b/Source/ThirdParty/FreeType/src/sfnt/ttbdf.h index ae521c60b6..398b620600 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttbdf.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttbdf.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (specification). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttcmap.c b/Source/ThirdParty/FreeType/src/sfnt/ttcmap.c index e48c15c65a..5afa6ae4b7 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttcmap.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttcmap.h b/Source/ThirdParty/FreeType/src/sfnt/ttcmap.h index 2273cbd961..83f12df241 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttcmap.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttcmapc.h b/Source/ThirdParty/FreeType/src/sfnt/ttcmapc.h index 7c732fbd36..9a5e70825e 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttcmapc.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ /* */ /* TT CMAP classes definitions (specification only). */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttkern.c b/Source/ThirdParty/FreeType/src/sfnt/ttkern.c index 6f9fa522d5..c97e5789ac 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttkern.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -108,8 +108,8 @@ p_next = p_limit; /* only use horizontal kerning tables */ - if ( ( coverage & ~8U ) != 0x0001 || - p + 8 > p_limit ) + if ( ( coverage & 3U ) != 0x0001 || + p + 8 > p_next ) goto NextTable; num_pairs = FT_NEXT_USHORT( p ); @@ -214,8 +214,7 @@ if ( ( face->kern_avail_bits & mask ) == 0 ) goto NextTable; - if ( p + 8 > next ) - goto NextTable; + FT_ASSERT( p + 8 <= next ); /* tested in tt_face_load_kern */ num_pairs = FT_NEXT_USHORT( p ); p += 6; diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttkern.h b/Source/ThirdParty/FreeType/src/sfnt/ttkern.h index 85dd5c31ae..db1a30bdb0 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttkern.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttload.c b/Source/ThirdParty/FreeType/src/sfnt/ttload.c index d615bba04a..df99baa53e 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttload.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttload.c @@ -5,7 +5,7 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -808,7 +808,6 @@ FT_Memory memory = stream->memory; FT_ULong table_pos, table_len; FT_ULong storage_start, storage_limit; - FT_UInt count; TT_NameTable table; static const FT_Frame_Field name_table_fields[] = @@ -826,7 +825,7 @@ static const FT_Frame_Field name_record_fields[] = { #undef FT_STRUCTURE -#define FT_STRUCTURE TT_NameEntryRec +#define FT_STRUCTURE TT_NameRec /* no FT_FRAME_START */ FT_FRAME_USHORT( platformID ), @@ -838,6 +837,17 @@ FT_FRAME_END }; + static const FT_Frame_Field langTag_record_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_LangTagRec + + /* no FT_FRAME_START */ + FT_FRAME_USHORT( stringLength ), + FT_FRAME_USHORT( stringOffset ), + FT_FRAME_END + }; + table = &face->name_table; table->stream = stream; @@ -848,18 +858,17 @@ table_pos = FT_STREAM_POS(); - if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) goto Exit; - /* Some popular Asian fonts have an invalid `storageOffset' value */ - /* (it should be at least "6 + 12*num_names"). However, the string */ - /* offsets, computed as "storageOffset + entry->stringOffset", are */ - /* valid pointers within the name table... */ - /* */ - /* We thus can't check `storageOffset' right now. */ - /* */ - storage_start = table_pos + 6 + 12*table->numNameRecords; + /* Some popular Asian fonts have an invalid `storageOffset' value (it */ + /* should be at least `6 + 12*numNameRecords'). However, the string */ + /* offsets, computed as `storageOffset + entry->stringOffset', are */ + /* valid pointers within the name table... */ + /* */ + /* We thus can't check `storageOffset' right now. */ + /* */ + storage_start = table_pos + 6 + 12 * table->numNameRecords; storage_limit = table_pos + table_len; if ( storage_start > storage_limit ) @@ -869,18 +878,56 @@ goto Exit; } - /* Allocate the array of name records. */ - count = table->numNameRecords; - table->numNameRecords = 0; + /* `name' format 1 contains additional language tag records, */ + /* which we load first */ + if ( table->format == 1 ) + { + if ( FT_STREAM_SEEK( storage_start ) || + FT_READ_USHORT( table->numLangTagRecords ) ) + goto Exit; + + storage_start += 2 + 4 * table->numLangTagRecords; + + /* allocate language tag records array */ + if ( FT_NEW_ARRAY( table->langTags, table->numLangTagRecords ) || + FT_FRAME_ENTER( table->numLangTagRecords * 4 ) ) + goto Exit; - if ( FT_NEW_ARRAY( table->names, count ) || - FT_FRAME_ENTER( count * 12 ) ) + /* load language tags */ + { + TT_LangTag entry = table->langTags; + TT_LangTag limit = entry + table->numLangTagRecords; + + + for ( ; entry < limit; entry++ ) + { + (void)FT_STREAM_READ_FIELDS( langTag_record_fields, entry ); + + /* check that the langTag string is within the table */ + entry->stringOffset += table_pos + table->storageOffset; + if ( entry->stringOffset < storage_start || + entry->stringOffset + entry->stringLength > storage_limit ) + { + /* invalid entry; ignore it */ + entry->stringLength = 0; + } + } + } + + FT_FRAME_EXIT(); + + (void)FT_STREAM_SEEK( table_pos + 6 ); + } + + /* allocate name records array */ + if ( FT_NEW_ARRAY( table->names, table->numNameRecords ) || + FT_FRAME_ENTER( table->numNameRecords * 12 ) ) goto Exit; - /* Load the name records and determine how much storage is needed */ - /* to hold the strings themselves. */ + /* load name records */ { - TT_NameEntryRec* entry = table->names; + TT_Name entry = table->names; + FT_UInt count = table->numNameRecords; for ( ; count > 0; count-- ) @@ -897,22 +944,37 @@ if ( entry->stringOffset < storage_start || entry->stringOffset + entry->stringLength > storage_limit ) { - /* invalid entry - ignore it */ - entry->stringOffset = 0; - entry->stringLength = 0; + /* invalid entry; ignore it */ continue; } + /* assure that we have a valid language tag ID, and */ + /* that the corresponding langTag entry is valid, too */ + if ( table->format == 1 && entry->languageID >= 0x8000U ) + { + if ( entry->languageID - 0x8000U >= table->numLangTagRecords || + !table->langTags[entry->languageID - 0x8000U].stringLength ) + { + /* invalid entry; ignore it */ + continue; + } + } + entry++; } - table->numNameRecords = (FT_UInt)( entry - table->names ); + /* reduce array size to the actually used elements */ + count = (FT_UInt)( entry - table->names ); + (void)FT_RENEW_ARRAY( table->names, + table->numNameRecords, + count ); + table->numNameRecords = count; } FT_FRAME_EXIT(); /* everything went well, update face->num_names */ - face->num_names = (FT_UShort) table->numNameRecords; + face->num_names = (FT_UShort)table->numNameRecords; Exit: return error; @@ -922,7 +984,7 @@ /*************************************************************************/ /* */ /* <Function> */ - /* tt_face_free_names */ + /* tt_face_free_name */ /* */ /* <Description> */ /* Frees the name records. */ @@ -935,25 +997,36 @@ { FT_Memory memory = face->root.driver->root.memory; TT_NameTable table = &face->name_table; - TT_NameEntry entry = table->names; - FT_UInt count = table->numNameRecords; if ( table->names ) { - for ( ; count > 0; count--, entry++ ) - { + TT_Name entry = table->names; + TT_Name limit = entry + table->numNameRecords; + + + for ( ; entry < limit; entry++ ) FT_FREE( entry->string ); - entry->stringLength = 0; - } - /* free strings table */ FT_FREE( table->names ); } - table->numNameRecords = 0; - table->format = 0; - table->storageOffset = 0; + if ( table->langTags ) + { + TT_LangTag entry = table->langTags; + TT_LangTag limit = entry + table->numLangTagRecords; + + + for ( ; entry < limit; entry++ ) + FT_FREE( entry->string ); + + FT_FREE( table->langTags ); + } + + table->numNameRecords = 0; + table->numLangTagRecords = 0; + table->format = 0; + table->storageOffset = 0; } diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttload.h b/Source/ThirdParty/FreeType/src/sfnt/ttload.h index bec42b94b4..296da86ed3 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttload.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttload.h @@ -5,7 +5,7 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttmtx.c b/Source/ThirdParty/FreeType/src/sfnt/ttmtx.c index 8c5508e24e..394c6db85c 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttmtx.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,14 @@ #include "sferrors.h" + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields, */ + /* which are different. */ + /* */ + /* This ensures that `tt_face_load_hmtx' is able to read */ + /* both the horizontal and vertical headers. */ + + /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttmtx.h b/Source/ThirdParty/FreeType/src/sfnt/ttmtx.h index 78395def33..2b93ab2f0e 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttmtx.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttpost.c b/Source/ThirdParty/FreeType/src/sfnt/ttpost.c index ef81e63a31..540d5f2546 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttpost.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ /* PostScript name table processing for TrueType and OpenType fonts */ /* (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,6 +29,10 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H + + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + #include "ttpost.h" #include "sferrors.h" @@ -561,5 +565,12 @@ return FT_Err_Ok; } +#else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_post_dummy; + +#endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + /* END */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttpost.h b/Source/ThirdParty/FreeType/src/sfnt/ttpost.h index ede45fd84c..722485e32d 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttpost.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ /* PostScript name table processing for TrueType and OpenType fonts */ /* (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttsbit.c b/Source/ThirdParty/FreeType/src/sfnt/ttsbit.c index bf6ecca5a7..0c76a55779 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttsbit.c +++ b/Source/ThirdParty/FreeType/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Copyright 2013 by Google, Inc. */ @@ -24,6 +24,10 @@ #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H #include FT_BITMAP_H + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + #include "ttsbit.h" #include "sferrors.h" @@ -1460,6 +1464,9 @@ FT_Byte* p; FT_UNUSED( map ); +#ifndef FT_CONFIG_OPTION_USE_PNG + FT_UNUSED( metrics_only ); +#endif strike_index = face->sbit_strike_map[strike_index]; @@ -1647,5 +1654,12 @@ return error; } +#else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_sbit_dummy; + +#endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + -/* EOF */ +/* END */ diff --git a/Source/ThirdParty/FreeType/src/sfnt/ttsbit.h b/Source/ThirdParty/FreeType/src/sfnt/ttsbit.h index d8a8167083..e859ddda45 100644 --- a/Source/ThirdParty/FreeType/src/sfnt/ttsbit.h +++ b/Source/ThirdParty/FreeType/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/smooth/ftgrays.c b/Source/ThirdParty/FreeType/src/smooth/ftgrays.c index ba42c9ca96..e9a3ce7a7c 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftgrays.c +++ b/Source/ThirdParty/FreeType/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ /* */ /* A new `perfect' anti-aliasing renderer (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -341,7 +341,8 @@ typedef ptrdiff_t FT_PtrDist; /* Compute `dividend / divisor' and return both its quotient and */ /* remainder, cast to a specific type. This macro also ensures that */ - /* the remainder is always positive. */ + /* the remainder is always positive. We use the remainder to keep */ + /* track of accumulating errors and compensate for them. */ #define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ FT_BEGIN_STMNT \ (quotient) = (type)( (dividend) / (divisor) ); \ @@ -567,9 +568,6 @@ typedef ptrdiff_t FT_PtrDist; /* Note that if a cell is to the left of the clipping region, it is */ /* actually set to the (min_ex-1) horizontal position. */ - /* All cells that are on the left of the clipping region go to the */ - /* min_ex - 1 horizontal position. */ - if ( ex < ras.min_ex ) ex = ras.min_ex - 1; @@ -600,7 +598,7 @@ typedef ptrdiff_t FT_PtrDist; TPos x2, TCoord y2 ) { - TCoord ex1, ex2, fx1, fx2, first, delta, mod; + TCoord ex1, ex2, fx1, fx2, first, dy, delta, mod; TPos p, dx; int incr; @@ -617,31 +615,27 @@ typedef ptrdiff_t FT_PtrDist; fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); - delta = y2 - y1; /* everything is located in a single cell. That is easy! */ /* */ if ( ex1 == ex2 ) - { - ras.area += (TArea)(( fx1 + fx2 ) * delta); - ras.cover += delta; - return; - } + goto End; /* ok, we'll have to render a run of adjacent cells on the same */ /* scanline... */ /* */ dx = x2 - x1; + dy = y2 - y1; if ( dx > 0 ) { - p = ( ONE_PIXEL - fx1 ) * delta; + p = ( ONE_PIXEL - fx1 ) * dy; first = ONE_PIXEL; incr = 1; } else { - p = fx1 * delta; + p = fx1 * dy; first = 0; incr = -1; dx = -dx; @@ -649,34 +643,31 @@ typedef ptrdiff_t FT_PtrDist; FT_DIV_MOD( TCoord, p, dx, delta, mod ); - ras.area += (TArea)(( fx1 + first ) * delta); + ras.area += (TArea)( ( fx1 + first ) * delta ); ras.cover += delta; - - ex1 += incr; + y1 += delta; + ex1 += incr; gray_set_cell( RAS_VAR_ ex1, ey ); - y1 += delta; if ( ex1 != ex2 ) { TCoord lift, rem; - p = ONE_PIXEL * ( y2 - y1 + delta ); + p = ONE_PIXEL * dy; FT_DIV_MOD( TCoord, p, dx, lift, rem ); - mod -= (int)dx; - do { delta = lift; mod += rem; - if ( mod >= 0 ) + if ( mod >= (TCoord)dx ) { mod -= (TCoord)dx; delta++; } - ras.area += (TArea)(ONE_PIXEL * delta); + ras.area += (TArea)( ONE_PIXEL * delta ); ras.cover += delta; y1 += delta; ex1 += incr; @@ -684,9 +675,13 @@ typedef ptrdiff_t FT_PtrDist; } while ( ex1 != ex2 ); } - delta = y2 - y1; - ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta); - ras.cover += delta; + fx1 = ONE_PIXEL - first; + + End: + dy = y2 - y1; + + ras.area += (TArea)( ( fx1 + fx2 ) * dy ); + ras.cover += dy; } @@ -798,13 +793,12 @@ typedef ptrdiff_t FT_PtrDist; p = ONE_PIXEL * dx; FT_DIV_MOD( TCoord, p, dy, lift, rem ); - mod -= (TCoord)dy; do { delta = lift; mod += rem; - if ( mod >= 0 ) + if ( mod >= (TCoord)dy ) { mod -= (TCoord)dy; delta++; @@ -1228,31 +1222,21 @@ typedef ptrdiff_t FT_PtrDist; static void gray_hline( RAS_ARG_ TCoord x, TCoord y, - TArea area, + TArea coverage, TCoord acount ) { - int coverage; - FT_Span span; - - - /* compute the coverage line's coverage, depending on the */ - /* outline fill rule */ - /* */ - /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ - /* */ - coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); - /* use range 0..256 */ + /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256 */ + coverage >>= PIXEL_BITS * 2 + 1 - 8; if ( coverage < 0 ) - coverage = -coverage; + coverage = -coverage - 1; + /* compute the line's coverage depending on the outline fill rule */ if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) { coverage &= 511; - if ( coverage > 256 ) - coverage = 512 - coverage; - else if ( coverage == 256 ) - coverage = 255; + if ( coverage >= 256 ) + coverage = 511 - coverage; } else { @@ -1263,6 +1247,9 @@ typedef ptrdiff_t FT_PtrDist; if ( ras.render_span ) /* for FT_RASTER_FLAG_DIRECT only */ { + FT_Span span; + + span.x = (short)x; span.len = (unsigned short)acount; span.coverage = (unsigned char)coverage; @@ -1307,21 +1294,18 @@ typedef ptrdiff_t FT_PtrDist; for ( y = ras.min_ey; y < ras.max_ey; y++ ) { PCell cell = ras.ycells[y - ras.min_ey]; - TCoord cover = 0; TCoord x = ras.min_ex; + TArea cover = 0; + TArea area; for ( ; cell != NULL; cell = cell->next ) { - TArea area; - - if ( cover != 0 && cell->x > x ) - gray_hline( RAS_VAR_ x, y, (TArea)cover * ( ONE_PIXEL * 2 ), - cell->x - x ); + gray_hline( RAS_VAR_ x, y, cover, cell->x - x ); - cover += cell->cover; - area = (TArea)cover * ( ONE_PIXEL * 2 ) - cell->area; + cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); + area = cover - cell->area; if ( area != 0 && cell->x >= ras.min_ex ) gray_hline( RAS_VAR_ cell->x, y, area, 1 ); @@ -1330,8 +1314,7 @@ typedef ptrdiff_t FT_PtrDist; } if ( cover != 0 ) - gray_hline( RAS_VAR_ x, y, (TArea)cover * ( ONE_PIXEL * 2 ), - ras.max_ex - x ); + gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x ); } FT_TRACE7(( "gray_sweep: end\n" )); @@ -1613,7 +1596,7 @@ typedef ptrdiff_t FT_PtrDist; return 0; Exit: - FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); + FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error )); return error; Invalid_Outline: diff --git a/Source/ThirdParty/FreeType/src/smooth/ftgrays.h b/Source/ThirdParty/FreeType/src/smooth/ftgrays.h index 21c2badcaf..a5447da1a9 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftgrays.h +++ b/Source/ThirdParty/FreeType/src/smooth/ftgrays.h @@ -4,7 +4,7 @@ /* */ /* FreeType smooth renderer declaration */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/smooth/ftsmerrs.h b/Source/ThirdParty/FreeType/src/smooth/ftsmerrs.h index a759b91c17..a528c61832 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftsmerrs.h +++ b/Source/ThirdParty/FreeType/src/smooth/ftsmerrs.h @@ -4,7 +4,7 @@ /* */ /* smooth renderer error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/smooth/ftsmooth.c b/Source/ThirdParty/FreeType/src/smooth/ftsmooth.c index 5f6aa60ef5..435854e673 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftsmooth.c +++ b/Source/ThirdParty/FreeType/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ /* */ /* Anti-aliasing renderer interface (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -122,6 +122,60 @@ FT_Bool have_outline_shifted = FALSE; FT_Bool have_buffer = FALSE; +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + + FT_Int lcd_extra = 0; + FT_LcdFiveTapFilter lcd_weights = { 0 }; + FT_Bool have_custom_weight = FALSE; + FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL; + + + if ( slot->face ) + { + FT_Char i; + + + for ( i = 0; i < FT_LCD_FILTER_FIVE_TAPS; i++ ) + if ( slot->face->internal->lcd_weights[i] != 0 ) + { + have_custom_weight = TRUE; + break; + } + } + + /* + * The LCD filter can be set library-wide and per-face. Face overrides + * library. If the face filter weights are all zero (the default), it + * means that the library default should be used. + */ + if ( have_custom_weight ) + { + /* + * A per-font filter is set. It always uses the default 5-tap + * in-place FIR filter that needs 2 extra pixels. + */ + ft_memcpy( lcd_weights, + slot->face->internal->lcd_weights, + FT_LCD_FILTER_FIVE_TAPS ); + lcd_filter_func = ft_lcd_filter_fir; + lcd_extra = 2; + } + else + { + /* + * The face's lcd_weights is {0, 0, 0, 0, 0}, meaning `use library + * default'. If the library is set to use no LCD filtering + * (lcd_filter_func == NULL), `lcd_filter_func' here is also set to + * NULL and the tests further below pass over the filtering process. + */ + ft_memcpy( lcd_weights, + slot->library->lcd_weights, + FT_LCD_FILTER_FIVE_TAPS ); + lcd_filter_func = slot->library->lcd_filter_func; + lcd_extra = slot->library->lcd_extra; + } + +#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ /* check glyph image format */ if ( slot->format != render->glyph_format ) @@ -177,28 +231,23 @@ height *= 3; #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - if ( slot->library->lcd_filter_func ) + if ( lcd_filter_func ) { - FT_Int extra = slot->library->lcd_extra; - - if ( hmul ) { - x_shift += 64 * ( extra >> 1 ); - x_left -= extra >> 1; - width += 3 * extra; + x_shift += 64 * ( lcd_extra >> 1 ); + x_left -= lcd_extra >> 1; + width += 3 * lcd_extra; pitch = FT_PAD_CEIL( width, 4 ); } if ( vmul ) { - y_shift += 64 * ( extra >> 1 ); - y_top += extra >> 1; - height += 3 * extra; + y_shift += 64 * ( lcd_extra >> 1 ); + y_top += lcd_extra >> 1; + height += 3 * lcd_extra; } } - #endif /* @@ -299,8 +348,8 @@ if ( error ) goto Exit; - if ( slot->library->lcd_filter_func ) - slot->library->lcd_filter_func( bitmap, mode, slot->library ); + if ( lcd_filter_func ) + lcd_filter_func( bitmap, mode, lcd_weights ); #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ diff --git a/Source/ThirdParty/FreeType/src/smooth/ftsmooth.h b/Source/ThirdParty/FreeType/src/smooth/ftsmooth.h index c7c28c244c..6dfd65726c 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftsmooth.h +++ b/Source/ThirdParty/FreeType/src/smooth/ftsmooth.h @@ -4,7 +4,7 @@ /* */ /* Anti-aliasing renderer interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,18 +27,11 @@ FT_BEGIN_HEADER -#ifndef FT_CONFIG_OPTION_NO_STD_RASTER - FT_DECLARE_RENDERER( ft_std_renderer_class ) -#endif - -#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER FT_DECLARE_RENDERER( ft_smooth_renderer_class ) FT_DECLARE_RENDERER( ft_smooth_lcd_renderer_class ) - FT_DECLARE_RENDERER( ft_smooth_lcd_v_renderer_class ) -#endif - + FT_DECLARE_RENDERER( ft_smooth_lcdv_renderer_class ) FT_END_HEADER diff --git a/Source/ThirdParty/FreeType/src/smooth/ftspic.c b/Source/ThirdParty/FreeType/src/smooth/ftspic.c index 6c2b2329b3..fb89be3488 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftspic.c +++ b/Source/ThirdParty/FreeType/src/smooth/ftspic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for smooth module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/smooth/ftspic.h b/Source/ThirdParty/FreeType/src/smooth/ftspic.h index fe76152770..9ddd1c7905 100644 --- a/Source/ThirdParty/FreeType/src/smooth/ftspic.h +++ b/Source/ThirdParty/FreeType/src/smooth/ftspic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for smooth module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/smooth/smooth.c b/Source/ThirdParty/FreeType/src/smooth/smooth.c index 97ca3e5995..e0460d9d46 100644 --- a/Source/ThirdParty/FreeType/src/smooth/smooth.c +++ b/Source/ThirdParty/FreeType/src/smooth/smooth.c @@ -4,7 +4,7 @@ /* */ /* FreeType anti-aliasing rasterer module component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,11 +17,11 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "ftspic.c" + #include "ftgrays.c" #include "ftsmooth.c" +#include "ftspic.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/truetype/truetype.c b/Source/ThirdParty/FreeType/src/truetype/truetype.c index 23e2ea00a7..301b82ad1c 100644 --- a/Source/ThirdParty/FreeType/src/truetype/truetype.c +++ b/Source/ThirdParty/FreeType/src/truetype/truetype.c @@ -4,7 +4,7 @@ /* */ /* FreeType TrueType driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,22 +17,16 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "ttpic.c" + #include "ttdriver.c" /* driver interface */ -#include "ttpload.c" /* tables loader */ #include "ttgload.c" /* glyph loader */ -#include "ttobjs.c" /* object manager */ - -#ifdef TT_USE_BYTECODE_INTERPRETER +#include "ttgxvar.c" /* gx distortable font */ #include "ttinterp.c" +#include "ttobjs.c" /* object manager */ +#include "ttpic.c" +#include "ttpload.c" /* tables loader */ #include "ttsubpix.c" -#endif - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.c" /* gx distortable font */ -#endif /* END */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttdriver.c b/Source/ThirdParty/FreeType/src/truetype/ttdriver.c index af8b205e31..a1653b241c 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttdriver.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ /* */ /* TrueType font driver implementation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -304,15 +304,17 @@ /* use the scaled metrics, even when tt_size_reset fails */ FT_Select_Metrics( size->face, strike_index ); - tt_size_reset( ttsize ); /* ignore return value */ + tt_size_reset( ttsize, 0 ); /* ignore return value */ } else { - SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; - FT_Size_Metrics* metrics = &size->metrics; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; + FT_Size_Metrics* size_metrics = &size->metrics; - error = sfnt->load_strike_metrics( ttface, strike_index, metrics ); + error = sfnt->load_strike_metrics( ttface, + strike_index, + size_metrics ); if ( error ) ttsize->strike_index = 0xFFFFFFFFUL; } @@ -354,15 +356,16 @@ if ( FT_IS_SCALABLE( size->face ) ) { - error = tt_size_reset( ttsize ); - ttsize->root.metrics = ttsize->metrics; + error = tt_size_reset( ttsize, 0 ); #ifdef TT_USE_BYTECODE_INTERPRETER /* for the `MPS' bytecode instruction we need the point size */ + if ( !error ) { - FT_UInt resolution = ttsize->metrics.x_ppem > ttsize->metrics.y_ppem - ? req->horiResolution - : req->vertResolution; + FT_UInt resolution = + ttsize->metrics->x_ppem > ttsize->metrics->y_ppem + ? req->horiResolution + : req->vertResolution; /* if we don't have a resolution value, assume 72dpi */ @@ -456,6 +459,11 @@ load_flags |= FT_LOAD_NO_HINTING; } + /* use hinted metrics only if we load a glyph with hinting */ + size->metrics = ( load_flags & FT_LOAD_NO_HINTING ) + ? &ttsize->metrics + : &size->hinted_metrics; + /* now load the glyph outline if necessary */ error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); @@ -502,12 +510,12 @@ (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ - (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ + (FT_VAdvance_Adjust_Func)tt_vadvance_adjust, /* vadvance_adjust */ (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ - (FT_Metrics_Adjust_Func) NULL /* metrics_adjust */ + (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */ ) #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttdriver.h b/Source/ThirdParty/FreeType/src/truetype/ttdriver.h index 74392bbd02..3bcba7f745 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttdriver.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttdriver.h @@ -4,7 +4,7 @@ /* */ /* High-level TrueType driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/tterrors.h b/Source/ThirdParty/FreeType/src/truetype/tterrors.h index 895989f5fd..a49f205156 100644 --- a/Source/ThirdParty/FreeType/src/truetype/tterrors.h +++ b/Source/ThirdParty/FreeType/src/truetype/tterrors.h @@ -4,7 +4,7 @@ /* */ /* TrueType error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttgload.c b/Source/ThirdParty/FreeType/src/truetype/ttgload.c index a0cdfc8902..b7a844a6c7 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttgload.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttgload.c @@ -4,7 +4,7 @@ /* */ /* TrueType Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,6 +18,7 @@ #include <ft2build.h> #include FT_INTERNAL_DEBUG_H +#include FT_CONFIG_CONFIG_H #include FT_INTERNAL_CALC_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H @@ -162,7 +163,7 @@ /* This may not be the right place for this, but it works... */ /* Note that we have to unconditionally load the tweaks since */ /* it is possible that glyphs individually switch ClearType's */ - /* backwards compatibility mode on and off. */ + /* backward compatibility mode on and off. */ sph_set_tweaks( loader, glyph_index ); } #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -194,39 +195,39 @@ if ( face->root.internal->incremental_interface && face->root.internal->incremental_interface->funcs->get_glyph_metrics ) { - FT_Incremental_MetricsRec metrics; + FT_Incremental_MetricsRec incr_metrics; FT_Error error; - metrics.bearing_x = loader->left_bearing; - metrics.bearing_y = 0; - metrics.advance = loader->advance; - metrics.advance_v = 0; + incr_metrics.bearing_x = loader->left_bearing; + incr_metrics.bearing_y = 0; + incr_metrics.advance = loader->advance; + incr_metrics.advance_v = 0; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, - glyph_index, FALSE, &metrics ); + glyph_index, FALSE, &incr_metrics ); if ( error ) goto Exit; - left_bearing = (FT_Short)metrics.bearing_x; - advance_width = (FT_UShort)metrics.advance; + left_bearing = (FT_Short)incr_metrics.bearing_x; + advance_width = (FT_UShort)incr_metrics.advance; #if 0 /* GWW: Do I do the same for vertical metrics? */ - metrics.bearing_x = 0; - metrics.bearing_y = loader->top_bearing; - metrics.advance = loader->vadvance; + incr_metrics.bearing_x = 0; + incr_metrics.bearing_y = loader->top_bearing; + incr_metrics.advance = loader->vadvance; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, - glyph_index, TRUE, &metrics ); + glyph_index, TRUE, &incr_metrics ); if ( error ) goto Exit; - top_bearing = (FT_Short)metrics.bearing_y; - advance_height = (FT_UShort)metrics.advance; + top_bearing = (FT_Short)incr_metrics.bearing_y; + advance_height = (FT_UShort)incr_metrics.advance; #endif /* 0 */ @@ -332,7 +333,6 @@ FT_Outline* outline; FT_UShort n_ins; FT_Int n_points; - FT_ULong tmp; FT_Byte *flag, *flag_limit; FT_Byte c, count; @@ -398,18 +398,21 @@ FT_TRACE5(( " Instructions size: %u\n", n_ins )); - /* check it */ - if ( ( limit - p ) < n_ins ) - { - FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = FT_THROW( Too_Many_Hints ); - goto Fail; - } - #ifdef TT_USE_BYTECODE_INTERPRETER if ( IS_HINTED( load->load_flags ) ) { + FT_ULong tmp; + + + /* check instructions size */ + if ( ( limit - p ) < n_ins ) + { + FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); + error = FT_THROW( Too_Many_Hints ); + goto Fail; + } + /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ /* and thus update the bytecode array size by ourselves */ @@ -775,8 +778,8 @@ } else { - loader->exec->metrics.x_scale = loader->size->metrics.x_scale; - loader->exec->metrics.y_scale = loader->size->metrics.y_scale; + loader->exec->metrics.x_scale = loader->size->metrics->x_scale; + loader->exec->metrics.y_scale = loader->size->metrics->y_scale; } #endif @@ -818,11 +821,11 @@ #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* Save possibly modified glyph phantom points unless in v40 backwards */ + /* Save possibly modified glyph phantom points unless in v40 backward */ /* compatibility mode, where no movement on the x axis means no reason */ /* to change bearings or advance widths. */ if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - !loader->exec->backwards_compatibility ) ) + !loader->exec->backward_compatibility ) ) { #endif loader->pp1 = zone->cur[zone->n_points - 4]; @@ -886,7 +889,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( loader->face->doblend && !loader->face->is_default_instance ) + if ( !loader->face->is_default_instance ) { /* Deltas apply to the unscaled data. */ error = TT_Vary_Apply_Glyph_Deltas( loader->face, @@ -923,7 +926,7 @@ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics.x_ppem; + FT_UInt ppem = loader->size->metrics->x_ppem; FT_String* style = face->root.style_name; FT_UInt x_scale_factor = 1000; #endif @@ -952,9 +955,9 @@ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || x_scale_factor != 1000 ) { - x_scale = FT_MulDiv( loader->size->metrics.x_scale, + x_scale = FT_MulDiv( loader->size->metrics->x_scale, (FT_Long)x_scale_factor, 1000 ); - y_scale = loader->size->metrics.y_scale; + y_scale = loader->size->metrics->y_scale; /* compensate for any scaling by de/emboldening; */ /* the amount was determined via experimentation */ @@ -974,8 +977,8 @@ /* scale the glyph */ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) { - x_scale = loader->size->metrics.x_scale; - y_scale = loader->size->metrics.y_scale; + x_scale = loader->size->metrics->x_scale; + y_scale = loader->size->metrics->y_scale; do_scale = TRUE; } @@ -1133,8 +1136,8 @@ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) { - FT_Fixed x_scale = loader->size->metrics.x_scale; - FT_Fixed y_scale = loader->size->metrics.y_scale; + FT_Fixed x_scale = loader->size->metrics->x_scale; + FT_Fixed y_scale = loader->size->metrics->y_scale; x = FT_MulFix( x, x_scale ); @@ -1392,7 +1395,7 @@ /* a utility function to retrieve i-th node from given FT_List */ static FT_ListNode ft_list_get_node_at( FT_List list, - FT_UInt index ) + FT_UInt idx ) { FT_ListNode cur; @@ -1402,10 +1405,10 @@ for ( cur = list->head; cur; cur = cur->next ) { - if ( !index ) + if ( !idx ) return cur; - index--; + idx--; } return NULL; @@ -1467,8 +1470,8 @@ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) { - x_scale = loader->size->metrics.x_scale; - y_scale = loader->size->metrics.y_scale; + x_scale = loader->size->metrics->x_scale; + y_scale = loader->size->metrics->y_scale; } else { @@ -1574,7 +1577,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( loader->face->doblend && !loader->face->is_default_instance ) + if ( !loader->face->is_default_instance ) { /* a small outline structure with four elements for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ @@ -1709,7 +1712,7 @@ /* check whether we already have a composite glyph with this index */ if ( FT_List_Find( &loader->composites, - (void*)(unsigned long)glyph_index ) ) + FT_UINT_TO_POINTER( glyph_index ) ) ) { FT_TRACE1(( "TT_Load_Composite_Glyph:" " infinite recursion detected\n" )); @@ -1718,13 +1721,13 @@ } else if ( node ) - node->data = (void*)(unsigned long)glyph_index; + node->data = FT_UINT_TO_POINTER( glyph_index ); else { if ( FT_NEW( node ) ) goto Exit; - node->data = (void*)(unsigned long)glyph_index; + node->data = FT_UINT_TO_POINTER( glyph_index ); FT_List_Add( &loader->composites, node ); } @@ -1745,7 +1748,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->doblend && !face->is_default_instance ) + if ( !face->is_default_instance ) { short i, limit; FT_SubGlyph subglyph; @@ -2035,7 +2038,7 @@ y_scale = 0x10000L; if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - y_scale = size->root.metrics.y_scale; + y_scale = size->metrics->y_scale; if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) FT_Outline_Get_CBox( &glyph->outline, &bbox ); @@ -2050,24 +2053,24 @@ glyph->metrics.horiBearingY = bbox.yMax; glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; - /* Adjust advance width to the value contained in the hdmx table */ - /* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */ - /* mode of the v40 interpreter is active. See `ttinterp.h' for */ - /* details on backwards compatibility mode. */ + /* Adjust advance width to the value contained in the hdmx table */ + /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */ + /* mode of the v40 interpreter is active. See `ttinterp.h' for */ + /* details on backward compatibility mode. */ if ( #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - ( loader->exec && loader->exec->backwards_compatibility ) ) && + !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + ( loader->exec && loader->exec->backward_compatibility ) ) && #endif - !face->postscript.isFixedPitch && - IS_HINTED( loader->load_flags ) && - !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) + !face->postscript.isFixedPitch && + IS_HINTED( loader->load_flags ) && + !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) { FT_Byte* widthp; widthp = tt_face_get_device_metrics( face, - size->root.metrics.x_ppem, + size->metrics->x_ppem, glyph_index ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY @@ -2149,7 +2152,7 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL { FT_Incremental_InterfaceRec* incr; - FT_Incremental_MetricsRec metrics; + FT_Incremental_MetricsRec incr_metrics; FT_Error error; @@ -2159,19 +2162,19 @@ /* overriding metrics for this glyph. */ if ( incr && incr->funcs->get_glyph_metrics ) { - metrics.bearing_x = 0; - metrics.bearing_y = top; - metrics.advance = advance; + incr_metrics.bearing_x = 0; + incr_metrics.bearing_y = top; + incr_metrics.advance = advance; error = incr->funcs->get_glyph_metrics( incr->object, glyph_index, TRUE, - &metrics ); + &incr_metrics ); if ( error ) return error; - top = metrics.bearing_y; - advance = metrics.advance; + top = incr_metrics.bearing_y; + advance = incr_metrics.advance; } } @@ -2213,7 +2216,7 @@ SFNT_Service sfnt; FT_Stream stream; FT_Error error; - TT_SBit_MetricsRec metrics; + TT_SBit_MetricsRec sbit_metrics; face = (TT_Face)glyph->face; @@ -2226,34 +2229,34 @@ (FT_UInt)load_flags, stream, &glyph->bitmap, - &metrics ); + &sbit_metrics ); if ( !error ) { glyph->outline.n_points = 0; glyph->outline.n_contours = 0; - glyph->metrics.width = (FT_Pos)metrics.width * 64; - glyph->metrics.height = (FT_Pos)metrics.height * 64; + glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64; + glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64; - glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64; - glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64; - glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64; + glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64; + glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64; + glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64; - glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64; - glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64; - glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64; + glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64; + glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64; + glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64; glyph->format = FT_GLYPH_FORMAT_BITMAP; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { - glyph->bitmap_left = metrics.vertBearingX; - glyph->bitmap_top = metrics.vertBearingY; + glyph->bitmap_left = sbit_metrics.vertBearingX; + glyph->bitmap_top = sbit_metrics.vertBearingY; } else { - glyph->bitmap_left = metrics.horiBearingX; - glyph->bitmap_top = metrics.horiBearingY; + glyph->bitmap_left = sbit_metrics.horiBearingX; + glyph->bitmap_top = sbit_metrics.horiBearingY; } } @@ -2270,17 +2273,17 @@ FT_Int32 load_flags, FT_Bool glyf_table_only ) { - FT_Error error; - TT_Face face; FT_Stream stream; + #ifdef TT_USE_BYTECODE_INTERPRETER + FT_Error error; FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); -#endif #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face ); #endif +#endif face = (TT_Face)glyph->face; @@ -2634,11 +2637,11 @@ if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance, - size->root.metrics.x_scale ); + size->metrics->x_scale ); if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance ) glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance, - size->root.metrics.y_scale ); + size->metrics->y_scale ); } return FT_Err_Ok; @@ -2649,14 +2652,20 @@ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) - return FT_THROW( Invalid_Size_Handle ); + { + error = FT_THROW( Invalid_Size_Handle ); + goto Exit; + } if ( load_flags & FT_LOAD_SBITS_ONLY ) - return FT_THROW( Invalid_Argument ); + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); if ( error ) - return error; + goto Exit; glyph->format = FT_GLYPH_FORMAT_OUTLINE; glyph->num_subglyphs = 0; @@ -2728,9 +2737,16 @@ /* TrueType glyphs at all sizes using the bytecode interpreter. */ /* */ if ( !( load_flags & FT_LOAD_NO_SCALE ) && - size->root.metrics.y_ppem < 24 ) + size->metrics->y_ppem < 24 ) glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + Exit: +#ifdef FT_DEBUG_LEVEL_TRACE + if ( error ) + FT_TRACE1(( " failed (error code 0x%x)\n", + error )); +#endif + return error; } diff --git a/Source/ThirdParty/FreeType/src/truetype/ttgload.h b/Source/ThirdParty/FreeType/src/truetype/ttgload.h index bfa29e4ff8..1dd6c841db 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttgload.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttgload.h @@ -4,7 +4,7 @@ /* */ /* TrueType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttgxvar.c b/Source/ThirdParty/FreeType/src/truetype/ttgxvar.c index cf4f7b17a9..0cedb6bdfa 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttgxvar.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,10 +22,6 @@ /* */ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */ /* */ - /* The documentation for `fvar' is inconsistent. At one point it says */ - /* that `countSizePairs' should be 3, at another point 2. It should */ - /* be 2. */ - /* */ /* The documentation for `gvar' is not intelligible; `cvar' refers you */ /* to `gvar' and is thus also incomprehensible. */ /* */ @@ -49,7 +45,9 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_TRUETYPE_TAGS_H +#include FT_TRUETYPE_IDS_H #include FT_MULTIPLE_MASTERS_H +#include FT_LIST_H #include "ttpload.h" #include "ttgxvar.h" @@ -322,7 +320,7 @@ FT_TRACE2(( "AVAR " )); - blend->avar_checked = TRUE; + blend->avar_loaded = TRUE; error = face->goto_table( face, TTAG_avar, stream, &table_len ); if ( error ) { @@ -346,7 +344,7 @@ if ( axisCount != (FT_Long)blend->mmvar->num_axis ) { - FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n" + FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `fvar'\n" " table are different\n" )); goto Exit; } @@ -396,359 +394,307 @@ /* some macros we need */ #define FT_FIXED_ONE ( (FT_Fixed)0x10000 ) - #define FT_fdot14ToFixed( x ) \ - ( ( (FT_Fixed)( (FT_Int16)(x) ) ) << 2 ) - #define FT_intToFixed( i ) \ - ( (FT_Fixed)( (FT_UInt32)(i) << 16 ) ) + #define FT_fdot14ToFixed( x ) \ + ( (FT_Fixed)( (FT_ULong)(x) << 2 ) ) + #define FT_intToFixed( i ) \ + ( (FT_Fixed)( (FT_ULong)(i) << 16 ) ) #define FT_fixedToInt( x ) \ ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) ) - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_load_hvar */ - /* */ - /* <Description> */ - /* Parse the `HVAR' table and set `blend->hvar_loaded' to TRUE. */ - /* */ - /* On success, `blend->hvar_checked' is set to TRUE. */ - /* */ - /* Some memory may remain allocated on error; it is always freed in */ - /* `tt_done_blend', however. */ - /* */ - /* <InOut> */ - /* face :: The font face. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ static FT_Error - ft_var_load_hvar( TT_Face face ) + ft_var_load_item_variation_store( TT_Face face, + FT_ULong offset, + GX_ItemVarStore itemStore ) { FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; - GX_Blend blend = face->blend; - FT_Error error; - FT_UShort majorVersion; - FT_ULong table_len; - FT_ULong table_offset; - FT_ULong store_offset; + FT_UShort format; + FT_ULong region_offset; + FT_UInt i, j, k; + FT_UInt shortDeltaCount; - FT_ULong* dataOffsetArray = NULL; + GX_Blend blend = face->blend; + GX_ItemVarData varData; + FT_ULong* dataOffsetArray = NULL; - blend->hvar_loaded = TRUE; - FT_TRACE2(( "HVAR " )); + if ( FT_STREAM_SEEK( offset ) || + FT_READ_USHORT( format ) ) + goto Exit; - error = face->goto_table( face, TTAG_HVAR, stream, &table_len ); - if ( error ) + if ( format != 1 ) { - FT_TRACE2(( "is missing\n" )); + FT_TRACE2(( "ft_var_load_item_variation_store: bad store format %d\n", + format )); + error = FT_THROW( Invalid_Table ); goto Exit; } - table_offset = FT_STREAM_POS(); - - /* skip minor version */ - if ( FT_READ_USHORT( majorVersion ) || - FT_STREAM_SKIP( 2 ) ) + /* read top level fields */ + if ( FT_READ_ULONG( region_offset ) || + FT_READ_USHORT( itemStore->dataCount ) ) goto Exit; - if ( majorVersion != 1 ) + + /* we need at least one entry in `itemStore->varData' */ + if ( !itemStore->dataCount ) { - FT_TRACE2(( "bad table version %d\n", majorVersion )); + FT_TRACE2(( "ft_var_load_item_variation_store: missing varData\n" )); error = FT_THROW( Invalid_Table ); goto Exit; } - /* skip map offset */ - if ( FT_READ_ULONG( store_offset ) || - FT_STREAM_SKIP( 4 ) ) + /* make temporary copy of item variation data offsets; */ + /* we will parse region list first, then come back */ + if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) ) goto Exit; - /* parse item variation store */ + for ( i = 0; i < itemStore->dataCount; i++ ) { - FT_UShort format; - FT_ULong region_offset; - FT_UInt i, j, k; - FT_UInt shortDeltaCount; - - GX_HVStore itemStore; - GX_HVarTable hvarTable; - GX_HVarData hvarData; - - - if ( FT_STREAM_SEEK( table_offset + store_offset ) || - FT_READ_USHORT( format ) ) + if ( FT_READ_ULONG( dataOffsetArray[i] ) ) goto Exit; - if ( format != 1 ) - { - FT_TRACE2(( "bad store format %d\n", format )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + } - if ( FT_NEW( blend->hvar_table ) ) /* allocate table at top level */ - goto Exit; + /* parse array of region records (region list) */ + if ( FT_STREAM_SEEK( offset + region_offset ) ) + goto Exit; - hvarTable = blend->hvar_table; - itemStore = &hvarTable->itemStore; + if ( FT_READ_USHORT( itemStore->axisCount ) || + FT_READ_USHORT( itemStore->regionCount ) ) + goto Exit; - /* read top level fields */ - if ( FT_READ_ULONG( region_offset ) || - FT_READ_USHORT( itemStore->dataCount ) ) - goto Exit; + if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis ) + { + FT_TRACE2(( "ft_var_load_item_variation_store:" + " number of axes in item variation store\n" + " " + " and `fvar' table are different\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - /* make temporary copy of item variation data offsets; */ - /* we will parse region list first, then come back */ - if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) ) - goto Exit; + if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) ) + goto Exit; - for ( i = 0; i < itemStore->dataCount; i++ ) - { - if ( FT_READ_ULONG( dataOffsetArray[i] ) ) - goto Exit; - } + for ( i = 0; i < itemStore->regionCount; i++ ) + { + GX_AxisCoords axisCoords; - /* parse array of region records (region list) */ - if ( FT_STREAM_SEEK( table_offset + store_offset + region_offset ) ) - goto Exit; - if ( FT_READ_USHORT( itemStore->axisCount ) || - FT_READ_USHORT( itemStore->regionCount ) ) + if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, + itemStore->axisCount ) ) goto Exit; - if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) ) - goto Exit; + axisCoords = itemStore->varRegionList[i].axisList; - for ( i = 0; i < itemStore->regionCount; i++ ) + for ( j = 0; j < itemStore->axisCount; j++ ) { - GX_AxisCoords axisCoords; + FT_Short start, peak, end; - if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, - itemStore->axisCount ) ) + if ( FT_READ_SHORT( start ) || + FT_READ_SHORT( peak ) || + FT_READ_SHORT( end ) ) goto Exit; - axisCoords = itemStore->varRegionList[i].axisList; + axisCoords[j].startCoord = FT_fdot14ToFixed( start ); + axisCoords[j].peakCoord = FT_fdot14ToFixed( peak ); + axisCoords[j].endCoord = FT_fdot14ToFixed( end ); + } + } - for ( j = 0; j < itemStore->axisCount; j++ ) - { - FT_Short start, peak, end; + /* end of region list parse */ + /* use dataOffsetArray now to parse varData items */ + if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) ) + goto Exit; - if ( FT_READ_SHORT( start ) || - FT_READ_SHORT( peak ) || - FT_READ_SHORT( end ) ) - goto Exit; + for ( i = 0; i < itemStore->dataCount; i++ ) + { + varData = &itemStore->varData[i]; - axisCoords[j].startCoord = FT_fdot14ToFixed( start ); - axisCoords[j].peakCoord = FT_fdot14ToFixed( peak ); - axisCoords[j].endCoord = FT_fdot14ToFixed( end ); - } - } + if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) ) + goto Exit; - /* end of region list parse */ + if ( FT_READ_USHORT( varData->itemCount ) || + FT_READ_USHORT( shortDeltaCount ) || + FT_READ_USHORT( varData->regionIdxCount ) ) + goto Exit; - /* use dataOffsetArray now to parse varData items */ - if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) ) + /* check some data consistency */ + if ( shortDeltaCount > varData->regionIdxCount ) + { + FT_TRACE2(( "bad short count %d or region count %d\n", + shortDeltaCount, + varData->regionIdxCount )); + error = FT_THROW( Invalid_Table ); goto Exit; + } - for ( i = 0; i < itemStore->dataCount; i++ ) + if ( varData->regionIdxCount > itemStore->regionCount ) { - hvarData = &itemStore->varData[i]; + FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n", + varData->regionIdxCount, + i )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - if ( FT_STREAM_SEEK( table_offset + - store_offset + - dataOffsetArray[i] ) ) - goto Exit; + /* parse region indices */ + if ( FT_NEW_ARRAY( varData->regionIndices, + varData->regionIdxCount ) ) + goto Exit; - if ( FT_READ_USHORT( hvarData->itemCount ) || - FT_READ_USHORT( shortDeltaCount ) || - FT_READ_USHORT( hvarData->regionIdxCount ) ) + for ( j = 0; j < varData->regionIdxCount; j++ ) + { + if ( FT_READ_USHORT( varData->regionIndices[j] ) ) goto Exit; - /* check some data consistency */ - if ( shortDeltaCount > hvarData->regionIdxCount ) + if ( varData->regionIndices[j] >= itemStore->regionCount ) { - FT_TRACE2(( "bad short count %d or region count %d\n", - shortDeltaCount, - hvarData->regionIdxCount )); + FT_TRACE2(( "bad region index %d\n", + varData->regionIndices[j] )); error = FT_THROW( Invalid_Table ); goto Exit; } + } - if ( hvarData->regionIdxCount > itemStore->regionCount ) + /* Parse delta set. */ + /* */ + /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes */ + /* each; on output, deltas are expanded to `regionIdxCount' shorts */ + /* each. */ + if ( FT_NEW_ARRAY( varData->deltaSet, + varData->regionIdxCount * varData->itemCount ) ) + goto Exit; + + /* the delta set is stored as a 2-dimensional array of shorts; */ + /* sign-extend signed bytes to signed shorts */ + for ( j = 0; j < varData->itemCount * varData->regionIdxCount; ) + { + for ( k = 0; k < shortDeltaCount; k++, j++ ) { - FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n", - hvarData->regionIdxCount, - i )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + /* read the short deltas */ + FT_Short delta; - /* parse region indices */ - if ( FT_NEW_ARRAY( hvarData->regionIndices, - hvarData->regionIdxCount ) ) - goto Exit; - for ( j = 0; j < hvarData->regionIdxCount; j++ ) - { - if ( FT_READ_USHORT( hvarData->regionIndices[j] ) ) + if ( FT_READ_SHORT( delta ) ) goto Exit; - if ( hvarData->regionIndices[j] >= itemStore->regionCount ) - { - FT_TRACE2(( "bad region index %d\n", - hvarData->regionIndices[j] )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + varData->deltaSet[j] = delta; } - /* Parse delta set. */ - /* */ - /* On input, deltas are ( shortDeltaCount + regionIdxCount ) bytes */ - /* each; on output, deltas are expanded to `regionIdxCount' shorts */ - /* each. */ - if ( FT_NEW_ARRAY( hvarData->deltaSet, - hvarData->regionIdxCount * hvarData->itemCount ) ) - goto Exit; - - /* the delta set is stored as a 2-dimensional array of shorts; */ - /* sign-extend signed bytes to signed shorts */ - for ( j = 0; j < hvarData->itemCount * hvarData->regionIdxCount; ) + for ( ; k < varData->regionIdxCount; k++, j++ ) { - for ( k = 0; k < shortDeltaCount; k++, j++ ) - { - /* read the short deltas */ - FT_Short delta; - - - if ( FT_READ_SHORT( delta ) ) - goto Exit; + /* read the (signed) byte deltas */ + FT_Char delta; - hvarData->deltaSet[j] = delta; - } - - for ( ; k < hvarData->regionIdxCount; k++, j++ ) - { - /* read the (signed) byte deltas */ - FT_Char delta; + if ( FT_READ_CHAR( delta ) ) + goto Exit; - if ( FT_READ_CHAR( delta ) ) - goto Exit; - - hvarData->deltaSet[j] = delta; - } + varData->deltaSet[j] = delta; } } } - /* end parse item variation store */ - - /* parse width map */ - { - GX_WidthMap widthMap; + Exit: + FT_FREE( dataOffsetArray ); - FT_UShort format; - FT_UInt entrySize; - FT_UInt innerBitCount; - FT_UInt innerIndexMask; - FT_UInt i, j; + return error; + } - widthMap = &blend->hvar_table->widthMap; + static FT_Error + ft_var_load_delta_set_index_mapping( TT_Face face, + FT_ULong offset, + GX_DeltaSetIdxMap map, + GX_ItemVarStore itemStore ) + { + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; - if ( FT_READ_USHORT( format ) || - FT_READ_USHORT( widthMap->mapCount ) ) - goto Exit; + FT_Error error; - if ( format & 0xFFC0 ) - { - FT_TRACE2(( "bad map format %d\n", format )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + FT_UShort format; + FT_UInt entrySize; + FT_UInt innerBitCount; + FT_UInt innerIndexMask; + FT_UInt i, j; - /* bytes per entry: 1, 2, 3, or 4 */ - entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; - innerBitCount = ( format & 0x000F ) + 1; - innerIndexMask = ( 1 << innerBitCount ) - 1; - if ( FT_NEW_ARRAY( widthMap->innerIndex, widthMap->mapCount ) ) - goto Exit; + if ( FT_STREAM_SEEK( offset ) || + FT_READ_USHORT( format ) || + FT_READ_USHORT( map->mapCount ) ) + goto Exit; - if ( FT_NEW_ARRAY( widthMap->outerIndex, widthMap->mapCount ) ) - goto Exit; + if ( format & 0xFFC0 ) + { + FT_TRACE2(( "bad map format %d\n", format )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - for ( i = 0; i < widthMap->mapCount; i++ ) - { - FT_UInt mapData = 0; - FT_UInt outerIndex, innerIndex; + /* bytes per entry: 1, 2, 3, or 4 */ + entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; + innerBitCount = ( format & 0x000F ) + 1; + innerIndexMask = ( 1 << innerBitCount ) - 1; + if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) ) + goto Exit; - /* read map data one unsigned byte at a time, big endian */ - for ( j = 0; j < entrySize; j++ ) - { - FT_Byte data; + if ( FT_NEW_ARRAY( map->outerIndex, map->mapCount ) ) + goto Exit; + for ( i = 0; i < map->mapCount; i++ ) + { + FT_UInt mapData = 0; + FT_UInt outerIndex, innerIndex; - if ( FT_READ_BYTE( data ) ) - goto Exit; - mapData = ( mapData << 8 ) | data; - } + /* read map data one unsigned byte at a time, big endian */ + for ( j = 0; j < entrySize; j++ ) + { + FT_Byte data; - outerIndex = mapData >> innerBitCount; - if ( outerIndex >= blend->hvar_table->itemStore.dataCount ) - { - FT_TRACE2(( "outerIndex[%d] == %d out of range\n", - i, - outerIndex )); - error = FT_THROW( Invalid_Table ); + if ( FT_READ_BYTE( data ) ) goto Exit; - } - - widthMap->outerIndex[i] = outerIndex; - innerIndex = mapData & innerIndexMask; + mapData = ( mapData << 8 ) | data; + } - if ( innerIndex >= - blend->hvar_table->itemStore.varData[outerIndex].itemCount ) - { - FT_TRACE2(( "innerIndex[%d] == %d out of range\n", - i, - innerIndex )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + outerIndex = mapData >> innerBitCount; - widthMap->innerIndex[i] = innerIndex; + if ( outerIndex >= itemStore->dataCount ) + { + FT_TRACE2(( "outerIndex[%d] == %d out of range\n", + i, + outerIndex )); + error = FT_THROW( Invalid_Table ); + goto Exit; } - } - /* end parse width map */ + map->outerIndex[i] = outerIndex; - FT_TRACE2(( "loaded\n" )); - error = FT_Err_Ok; + innerIndex = mapData & innerIndexMask; - Exit: - FT_FREE( dataOffsetArray ); - - if ( !error ) - { - blend->hvar_checked = TRUE; + if ( innerIndex >= itemStore->varData[outerIndex].itemCount ) + { + FT_TRACE2(( "innerIndex[%d] == %d out of range\n", + i, + innerIndex )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - /* TODO: implement other HVAR stuff */ - face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE; + map->innerIndex[i] = innerIndex; } + Exit: return error; } @@ -756,86 +702,181 @@ /*************************************************************************/ /* */ /* <Function> */ - /* tt_hadvance_adjust */ + /* ft_var_load_hvvar */ /* */ /* <Description> */ - /* Apply HVAR advance width adjustment of a given glyph. */ + /* If `vertical' is zero, parse the `HVAR' table and set */ + /* `blend->hvar_loaded' to TRUE. On success, `blend->hvar_checked' */ + /* is set to TRUE. */ /* */ - /* <Input> */ - /* gindex :: The glyph index. */ + /* If `vertical' is not zero, parse the `VVAR' table and set */ + /* `blend->vvar_loaded' to TRUE. On success, `blend->vvar_checked' */ + /* is set to TRUE. */ + /* */ + /* Some memory may remain allocated on error; it is always freed in */ + /* `tt_done_blend', however. */ /* */ /* <InOut> */ - /* face :: The font face. */ + /* face :: The font face. */ /* */ - /* adelta :: Points to width value that gets modified. */ + /* <Return> */ + /* FreeType error code. 0 means success. */ /* */ - FT_LOCAL_DEF( FT_Error ) - tt_hadvance_adjust( TT_Face face, - FT_UInt gindex, - FT_Int *avalue ) + static FT_Error + ft_var_load_hvvar( TT_Face face, + FT_Bool vertical ) { - FT_Error error = FT_Err_Ok; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; - GX_HVarData varData; + GX_Blend blend = face->blend; - FT_UInt innerIndex, outerIndex; - FT_UInt master, j; - FT_Fixed netAdjustment = 0; /* accumulated adjustment */ - FT_Fixed scaledDelta; - FT_Short* deltaSet; - FT_Fixed delta; + GX_HVVarTable table; + FT_Error error; + FT_UShort majorVersion; + FT_ULong table_len; + FT_ULong table_offset; + FT_ULong store_offset; + FT_ULong widthMap_offset; - if ( !face->doblend || !face->blend ) - goto Exit; - if ( !face->blend->hvar_loaded ) + if ( vertical ) { - /* initialize hvar table */ - face->blend->hvar_error = ft_var_load_hvar( face ); + blend->vvar_loaded = TRUE; + + FT_TRACE2(( "VVAR " )); + + error = face->goto_table( face, TTAG_VVAR, stream, &table_len ); } + else + { + blend->hvar_loaded = TRUE; + + FT_TRACE2(( "HVAR " )); + + error = face->goto_table( face, TTAG_HVAR, stream, &table_len ); + } + + if ( error ) + { + FT_TRACE2(( "is missing\n" )); + goto Exit; + } + + table_offset = FT_STREAM_POS(); + + /* skip minor version */ + if ( FT_READ_USHORT( majorVersion ) || + FT_STREAM_SKIP( 2 ) ) + goto Exit; - if ( !face->blend->hvar_checked ) + if ( majorVersion != 1 ) { - error = face->blend->hvar_error; + FT_TRACE2(( "bad table version %d\n", majorVersion )); + error = FT_THROW( Invalid_Table ); goto Exit; } - /* advance width adjustments are always present in an `HVAR' table, */ - /* so need to test for this capability */ + if ( FT_READ_ULONG( store_offset ) || + FT_READ_ULONG( widthMap_offset ) ) + goto Exit; - if ( gindex >= face->blend->hvar_table->widthMap.mapCount ) + if ( vertical ) { - FT_TRACE2(( "gindex %d out of range\n", gindex )); - error = FT_THROW( Invalid_Argument ); + if ( FT_NEW( blend->vvar_table ) ) + goto Exit; + table = blend->vvar_table; + } + else + { + if ( FT_NEW( blend->hvar_table ) ) + goto Exit; + table = blend->hvar_table; + } + + error = ft_var_load_item_variation_store( + face, + table_offset + store_offset, + &table->itemStore ); + if ( error ) goto Exit; + + if ( widthMap_offset ) + { + error = ft_var_load_delta_set_index_mapping( + face, + table_offset + widthMap_offset, + &table->widthMap, + &table->itemStore ); + if ( error ) + goto Exit; + } + + FT_TRACE2(( "loaded\n" )); + error = FT_Err_Ok; + + Exit: + if ( !error ) + { + if ( vertical ) + { + blend->vvar_checked = TRUE; + + /* FreeType doesn't provide functions to quickly retrieve */ + /* TSB, BSB, or VORG values; we thus don't have to implement */ + /* support for those three item variation stores. */ + + face->variation_support |= TT_FACE_FLAG_VAR_VADVANCE; + } + else + { + blend->hvar_checked = TRUE; + + /* FreeType doesn't provide functions to quickly retrieve */ + /* LSB or RSB values; we thus don't have to implement */ + /* support for those two item variation stores. */ + + face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE; + } } - /* trust that HVAR parser has checked indices */ - outerIndex = face->blend->hvar_table->widthMap.outerIndex[gindex]; - innerIndex = face->blend->hvar_table->widthMap.innerIndex[gindex]; - varData = &face->blend->hvar_table->itemStore.varData[outerIndex]; - deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex]; + return error; + } + + + static FT_Int + ft_var_get_item_delta( TT_Face face, + GX_ItemVarStore itemStore, + FT_UInt outerIndex, + FT_UInt innerIndex ) + { + GX_ItemVarData varData; + FT_Short* deltaSet; + + FT_UInt master, j; + FT_Fixed netAdjustment = 0; /* accumulated adjustment */ + FT_Fixed scaledDelta; + FT_Fixed delta; + /* See pseudo code from `Font Variations Overview' */ /* in the OpenType specification. */ + varData = &itemStore->varData[outerIndex]; + deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex]; + /* outer loop steps through master designs to be blended */ for ( master = 0; master < varData->regionIdxCount; master++ ) { FT_Fixed scalar = FT_FIXED_ONE; FT_UInt regionIndex = varData->regionIndices[master]; - GX_AxisCoords axis = face->blend - ->hvar_table - ->itemStore.varRegionList[regionIndex] - .axisList; + GX_AxisCoords axis = itemStore->varRegionList[regionIndex].axisList; /* inner loop steps through axes in this region */ - for ( j = 0; - j < face->blend->hvar_table->itemStore.axisCount; - j++, axis++ ) + for ( j = 0; j < itemStore->axisCount; j++, axis++ ) { FT_Fixed axisScalar; @@ -875,29 +916,468 @@ axis->endCoord - axis->peakCoord ); } - /* take product of all the axis scalars */ - scalar = FT_MulFix( scalar, axisScalar ); + /* take product of all the axis scalars */ + scalar = FT_MulFix( scalar, axisScalar ); + + } /* per-axis loop */ + + /* get the scaled delta for this region */ + delta = FT_intToFixed( deltaSet[master] ); + scaledDelta = FT_MulFix( scalar, delta ); + + /* accumulate the adjustments from each region */ + netAdjustment = netAdjustment + scaledDelta; + + } /* per-region loop */ + + return FT_fixedToInt( netAdjustment ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_hvadvance_adjust */ + /* */ + /* <Description> */ + /* Apply `HVAR' advance width or `VVAR' advance height adjustment of */ + /* a given glyph. */ + /* */ + /* <Input> */ + /* gindex :: The glyph index. */ + /* */ + /* vertical :: If set, handle `VVAR' table. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + /* adelta :: Points to width or height value that gets modified. */ + /* */ + static FT_Error + tt_hvadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *avalue, + FT_Bool vertical ) + { + FT_Error error = FT_Err_Ok; + FT_UInt innerIndex, outerIndex; + FT_Int delta; + + GX_HVVarTable table; + + + if ( !face->doblend || !face->blend ) + goto Exit; + + if ( vertical ) + { + if ( !face->blend->vvar_loaded ) + { + /* initialize vvar table */ + face->blend->vvar_error = ft_var_load_hvvar( face, 1 ); + } + + if ( !face->blend->vvar_checked ) + { + error = face->blend->vvar_error; + goto Exit; + } + + table = face->blend->vvar_table; + } + else + { + if ( !face->blend->hvar_loaded ) + { + /* initialize hvar table */ + face->blend->hvar_error = ft_var_load_hvvar( face, 0 ); + } + + if ( !face->blend->hvar_checked ) + { + error = face->blend->hvar_error; + goto Exit; + } + + table = face->blend->hvar_table; + } + + /* advance width or height adjustments are always present in an */ + /* `HVAR' or `VVAR' table; no need to test for this capability */ + + if ( table->widthMap.innerIndex ) + { + FT_UInt idx = gindex; + + + if ( idx >= table->widthMap.mapCount ) + idx = table->widthMap.mapCount - 1; + + /* trust that HVAR parser has checked indices */ + outerIndex = table->widthMap.outerIndex[idx]; + innerIndex = table->widthMap.innerIndex[idx]; + } + else + { + GX_ItemVarData varData; + + + /* no widthMap data */ + outerIndex = 0; + innerIndex = gindex; + + varData = &table->itemStore.varData[outerIndex]; + if ( gindex >= varData->itemCount ) + { + FT_TRACE2(( "gindex %d out of range\n", gindex )); + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + } + + delta = ft_var_get_item_delta( face, + &table->itemStore, + outerIndex, + innerIndex ); + + FT_TRACE5(( "%s value %d adjusted by %d units (%s)\n", + vertical ? "vertical height" : "horizontal width", + *avalue, + delta, + vertical ? "VVAR" : "HVAR" )); + + *avalue += delta; + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + tt_hadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *avalue ) + { + return tt_hvadvance_adjust( face, gindex, avalue, 0 ); + } + + + FT_LOCAL_DEF( FT_Error ) + tt_vadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *avalue ) + { + return tt_hvadvance_adjust( face, gindex, avalue, 1 ); + } + + +#define GX_VALUE_SIZE 8 + + /* all values are FT_Short or FT_UShort entities; */ + /* we treat them consistently as FT_Short */ +#define GX_VALUE_CASE( tag, dflt ) \ + case MVAR_TAG_ ## tag : \ + p = (FT_Short*)&face->dflt; \ + break + +#define GX_GASP_CASE( idx ) \ + case MVAR_TAG_GASP_ ## idx : \ + if ( idx < face->gasp.numRanges - 1 ) \ + p = (FT_Short*)&face->gasp.gaspRanges[idx].maxPPEM; \ + else \ + p = NULL; \ + break + + + static FT_Short* + ft_var_get_value_pointer( TT_Face face, + FT_ULong mvar_tag ) + { + FT_Short* p; + + + switch ( mvar_tag ) + { + GX_GASP_CASE( 0 ); + GX_GASP_CASE( 1 ); + GX_GASP_CASE( 2 ); + GX_GASP_CASE( 3 ); + GX_GASP_CASE( 4 ); + GX_GASP_CASE( 5 ); + GX_GASP_CASE( 6 ); + GX_GASP_CASE( 7 ); + GX_GASP_CASE( 8 ); + GX_GASP_CASE( 9 ); + + GX_VALUE_CASE( CPHT, os2.sCapHeight ); + GX_VALUE_CASE( HASC, os2.sTypoAscender ); + GX_VALUE_CASE( HCLA, os2.usWinAscent ); + GX_VALUE_CASE( HCLD, os2.usWinDescent ); + GX_VALUE_CASE( HCOF, horizontal.caret_Offset ); + GX_VALUE_CASE( HCRN, horizontal.caret_Slope_Run ); + GX_VALUE_CASE( HCRS, horizontal.caret_Slope_Rise ); + GX_VALUE_CASE( HDSC, os2.sTypoDescender ); + GX_VALUE_CASE( HLGP, os2.sTypoLineGap ); + GX_VALUE_CASE( SBXO, os2.ySubscriptXOffset); + GX_VALUE_CASE( SBXS, os2.ySubscriptXSize ); + GX_VALUE_CASE( SBYO, os2.ySubscriptYOffset ); + GX_VALUE_CASE( SBYS, os2.ySubscriptYSize ); + GX_VALUE_CASE( SPXO, os2.ySuperscriptXOffset ); + GX_VALUE_CASE( SPXS, os2.ySuperscriptXSize ); + GX_VALUE_CASE( SPYO, os2.ySuperscriptYOffset ); + GX_VALUE_CASE( SPYS, os2.ySuperscriptYSize ); + GX_VALUE_CASE( STRO, os2.yStrikeoutPosition ); + GX_VALUE_CASE( STRS, os2.yStrikeoutSize ); + GX_VALUE_CASE( UNDO, postscript.underlinePosition ); + GX_VALUE_CASE( UNDS, postscript.underlineThickness ); + GX_VALUE_CASE( VASC, vertical.Ascender ); + GX_VALUE_CASE( VCOF, vertical.caret_Offset ); + GX_VALUE_CASE( VCRN, vertical.caret_Slope_Run ); + GX_VALUE_CASE( VCRS, vertical.caret_Slope_Rise ); + GX_VALUE_CASE( VDSC, vertical.Descender ); + GX_VALUE_CASE( VLGP, vertical.Line_Gap ); + GX_VALUE_CASE( XHGT, os2.sxHeight ); + + default: + /* ignore unknown tag */ + p = NULL; + } + + return p; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_load_mvar */ + /* */ + /* <Description> */ + /* Parse the `MVAR' table. */ + /* */ + /* Some memory may remain allocated on error; it is always freed in */ + /* `tt_done_blend', however. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + static void + ft_var_load_mvar( TT_Face face ) + { + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; + + GX_Blend blend = face->blend; + GX_ItemVarStore itemStore; + GX_Value value, limit; + + FT_Error error; + FT_UShort majorVersion; + FT_ULong table_len; + FT_ULong table_offset; + FT_UShort store_offset; + FT_ULong records_offset; + + + FT_TRACE2(( "MVAR " )); + + error = face->goto_table( face, TTAG_MVAR, stream, &table_len ); + if ( error ) + { + FT_TRACE2(( "is missing\n" )); + return; + } + + table_offset = FT_STREAM_POS(); + + /* skip minor version */ + if ( FT_READ_USHORT( majorVersion ) || + FT_STREAM_SKIP( 2 ) ) + return; + + if ( majorVersion != 1 ) + { + FT_TRACE2(( "bad table version %d\n", majorVersion )); + return; + } + + if ( FT_NEW( blend->mvar_table ) ) + return; + + /* skip reserved entry and value record size */ + if ( FT_STREAM_SKIP( 4 ) || + FT_READ_USHORT( blend->mvar_table->valueCount ) || + FT_READ_USHORT( store_offset ) ) + return; + + records_offset = FT_STREAM_POS(); + + error = ft_var_load_item_variation_store( + face, + table_offset + store_offset, + &blend->mvar_table->itemStore ); + if ( error ) + return; + + if ( FT_NEW_ARRAY( blend->mvar_table->values, + blend->mvar_table->valueCount ) ) + return; + + if ( FT_STREAM_SEEK( records_offset ) || + FT_FRAME_ENTER( blend->mvar_table->valueCount * GX_VALUE_SIZE ) ) + return; + + value = blend->mvar_table->values; + limit = value + blend->mvar_table->valueCount; + itemStore = &blend->mvar_table->itemStore; + + for ( ; value < limit; value++ ) + { + value->tag = FT_GET_ULONG(); + value->outerIndex = FT_GET_USHORT(); + value->innerIndex = FT_GET_USHORT(); + + if ( value->outerIndex >= itemStore->dataCount || + value->innerIndex >= itemStore->varData[value->outerIndex] + .itemCount ) + { + error = FT_THROW( Invalid_Table ); + break; + } + } + + FT_FRAME_EXIT(); + + if ( error ) + return; + + FT_TRACE2(( "loaded\n" )); + + value = blend->mvar_table->values; + limit = value + blend->mvar_table->valueCount; + + /* save original values of the data MVAR is going to modify */ + for ( ; value < limit; value++ ) + { + FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + + + if ( p ) + value->unmodified = *p; +#ifdef FT_DEBUG_LEVEL_TRACE + else + FT_TRACE1(( "ft_var_load_mvar: Ignoring unknown tag `%c%c%c%c'\n", + (FT_Char)( value->tag >> 24 ), + (FT_Char)( value->tag >> 16 ), + (FT_Char)( value->tag >> 8 ), + (FT_Char)( value->tag ) )); +#endif + } + + face->variation_support |= TT_FACE_FLAG_VAR_MVAR; + } + + + static FT_Error + tt_size_reset_iterator( FT_ListNode node, + void* user ) + { + TT_Size size = (TT_Size)node->data; + + FT_UNUSED( user ); + + + tt_size_reset( size, 1 ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_apply_mvar */ + /* */ + /* <Description> */ + /* Apply `MVAR' table adjustments. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + FT_LOCAL_DEF( void ) + tt_apply_mvar( TT_Face face ) + { + GX_Blend blend = face->blend; + GX_Value value, limit; + + + if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) + return; + + value = blend->mvar_table->values; + limit = value + blend->mvar_table->valueCount; + + for ( ; value < limit; value++ ) + { + FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + FT_Int delta; - } /* per-axis loop */ - /* get the scaled delta for this region */ - delta = FT_intToFixed( deltaSet[master] ); - scaledDelta = FT_MulFix( scalar, delta ); + delta = ft_var_get_item_delta( face, + &blend->mvar_table->itemStore, + value->outerIndex, + value->innerIndex ); - /* accumulate the adjustments from each region */ - netAdjustment = netAdjustment + scaledDelta; + if ( p ) + { + FT_TRACE5(( "value %c%c%c%c (%d units) adjusted by %d units (MVAR)\n", + (FT_Char)( value->tag >> 24 ), + (FT_Char)( value->tag >> 16 ), + (FT_Char)( value->tag >> 8 ), + (FT_Char)( value->tag ), + value->unmodified, + delta )); + + /* since we handle both signed and unsigned values as FT_Short, */ + /* ensure proper overflow arithmetic */ + *p = (FT_Short)( value->unmodified + (FT_Short)delta ); + } + } - } /* per-region loop */ + /* adjust all derived values */ + { + FT_Face root = &face->root; - /* apply the accumulated adjustment to derive the interpolated value */ - FT_TRACE5(( "horizontal width %d adjusted by %d units (HVAR)\n", - *avalue, - FT_fixedToInt( netAdjustment ) )); - *avalue += FT_fixedToInt( netAdjustment ); + if ( face->os2.version != 0xFFFFU ) + { + if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = face->os2.sTypoDescender; + + root->height = root->ascender - root->descender + + face->os2.sTypoLineGap; + } + else + { + root->ascender = (FT_Short)face->os2.usWinAscent; + root->descender = -(FT_Short)face->os2.usWinDescent; - Exit: - return error; + root->height = root->ascender - root->descender; + } + } + + root->underline_position = face->postscript.underlinePosition - + face->postscript.underlineThickness / 2; + root->underline_thickness = face->postscript.underlineThickness; + + /* iterate over all FT_Size objects and call `tt_size_reset' */ + /* to propagate the metrics changes */ + FT_List_Iterate( &root->sizes_list, + tt_size_reset_iterator, + NULL ); + } } @@ -1000,10 +1480,9 @@ goto Exit; } - /* rough sanity check: offsets can be either 2 or 4 bytes, */ - /* and a single variation needs at least 4 bytes per glyph */ + /* rough sanity check: offsets can be either 2 or 4 bytes */ if ( (FT_ULong)gvar_head.glyphCount * - ( ( gvar_head.flags & 1 ) ? 8 : 6 ) > table_len ) + ( ( gvar_head.flags & 1 ) ? 4 : 2 ) > table_len ) { FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" )); error = FT_THROW( Invalid_Table ); @@ -1216,6 +1695,190 @@ } + /* convert from design coordinates to normalized coordinates */ + + static void + ft_var_to_normalized( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords, + FT_Fixed* normalized ) + { + GX_Blend blend; + FT_MM_Var* mmvar; + FT_UInt i, j; + FT_Var_Axis* a; + GX_AVarSegment av; + + + blend = face->blend; + mmvar = blend->mmvar; + + if ( num_coords > mmvar->num_axis ) + { + FT_TRACE2(( "ft_var_to_normalized:" + " only using first %d of %d coordinates\n", + mmvar->num_axis, num_coords )); + num_coords = mmvar->num_axis; + } + + /* Axis normalization is a two-stage process. First we normalize */ + /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ + /* Then, if there's an `avar' table, we renormalize this range. */ + + FT_TRACE5(( "design coordinates:\n" )); + + a = mmvar->axis; + for ( i = 0; i < num_coords; i++, a++ ) + { + FT_Fixed coord = coords[i]; + + + FT_TRACE5(( " %.5f\n", coord / 65536.0 )); + if ( coord > a->maximum || coord < a->minimum ) + { + FT_TRACE1(( + "ft_var_to_normalized: design coordinate %.5f\n" + " is out of range [%.5f;%.5f]; clamping\n", + coord / 65536.0, + a->minimum / 65536.0, + a->maximum / 65536.0 )); + + if ( coord > a->maximum) + coord = a->maximum; + else + coord = a->minimum; + } + + if ( coord < a->def ) + normalized[i] = -FT_DivFix( coords[i] - a->def, + a->minimum - a->def ); + else if ( coord > a->def ) + normalized[i] = FT_DivFix( coords[i] - a->def, + a->maximum - a->def ); + else + normalized[i] = 0; + } + + FT_TRACE5(( "\n" )); + + for ( ; i < mmvar->num_axis; i++ ) + normalized[i] = 0; + + if ( blend->avar_segment ) + { + FT_TRACE5(( "normalized design coordinates" + " before applying `avar' data:\n" )); + + av = blend->avar_segment; + for ( i = 0; i < mmvar->num_axis; i++, av++ ) + { + for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) + { + if ( normalized[i] < av->correspondence[j].fromCoord ) + { + FT_TRACE5(( " %.5f\n", normalized[i] / 65536.0 )); + + normalized[i] = + FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord ) + + av->correspondence[j - 1].toCoord; + break; + } + } + } + } + } + + + /* convert from normalized coordinates to design coordinates */ + + static void + ft_var_to_design( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords, + FT_Fixed* design ) + { + GX_Blend blend; + FT_MM_Var* mmvar; + FT_Var_Axis* a; + + FT_UInt i, j, nc; + + + blend = face->blend; + + nc = num_coords; + if ( num_coords > blend->num_axis ) + { + FT_TRACE2(( "ft_var_to_design:" + " only using first %d of %d coordinates\n", + blend->num_axis, num_coords )); + nc = blend->num_axis; + } + + if ( face->doblend ) + { + for ( i = 0; i < nc; i++ ) + design[i] = coords[i]; + } + else + { + for ( i = 0; i < nc; i++ ) + design[i] = 0; + } + + for ( ; i < num_coords; i++ ) + design[i] = 0; + + if ( blend->avar_segment ) + { + GX_AVarSegment av = blend->avar_segment; + + + FT_TRACE5(( "design coordinates" + " after removing `avar' distortion:\n" )); + + for ( i = 0; i < nc; i++, av++ ) + { + for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) + { + if ( design[i] < av->correspondence[j].toCoord ) + { + design[i] = + FT_MulDiv( design[i] - av->correspondence[j - 1].toCoord, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord, + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord ) + + av->correspondence[j - 1].fromCoord; + + FT_TRACE5(( " %.5f\n", design[i] / 65536.0 )); + break; + } + } + } + } + + mmvar = blend->mmvar; + a = mmvar->axis; + + for ( i = 0; i < nc; i++, a++ ) + { + if ( design[i] < 0 ) + design[i] = a->def + FT_MulFix( design[i], + a->def - a->minimum ); + else if ( design[i] > 0 ) + design[i] = a->def + FT_MulFix( design[i], + a->maximum - a->def ); + else + design[i] = a->def; + } + } + + /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -1229,7 +1892,6 @@ { FT_Long version; FT_UShort offsetToData; - FT_UShort countSizePairs; FT_UShort axisCount; FT_UShort axisSize; FT_UShort instanceCount; @@ -1257,7 +1919,8 @@ /* */ /* <Description> */ /* Check that the font's `fvar' table is valid, parse it, and return */ - /* those data. */ + /* those data. It also loads (and parses) the `MVAR' table, if */ + /* possible. */ /* */ /* <InOut> */ /* face :: The font face. */ @@ -1279,14 +1942,17 @@ FT_ULong table_len; FT_Error error = FT_Err_Ok; FT_ULong fvar_start; - FT_Int i, j; + FT_UInt i, j; FT_MM_Var* mmvar = NULL; FT_Fixed* next_coords; + FT_Fixed* nsc; FT_String* next_name; FT_Var_Axis* a; + FT_Fixed* c; FT_Var_Named_Style* ns; GX_FVar_Head fvar_head; FT_Bool usePsName; + FT_UInt num_instances; static const FT_Frame_Field fvar_fields[] = { @@ -1295,13 +1961,13 @@ #define FT_STRUCTURE GX_FVar_Head FT_FRAME_START( 16 ), - FT_FRAME_LONG ( version ), - FT_FRAME_USHORT( offsetToData ), - FT_FRAME_USHORT( countSizePairs ), - FT_FRAME_USHORT( axisCount ), - FT_FRAME_USHORT( axisSize ), - FT_FRAME_USHORT( instanceCount ), - FT_FRAME_USHORT( instanceSize ), + FT_FRAME_LONG ( version ), + FT_FRAME_USHORT ( offsetToData ), + FT_FRAME_SKIP_SHORT, + FT_FRAME_USHORT ( axisCount ), + FT_FRAME_USHORT ( axisSize ), + FT_FRAME_USHORT ( instanceCount ), + FT_FRAME_USHORT ( instanceSize ), FT_FRAME_END }; @@ -1367,12 +2033,18 @@ if ( FT_NEW( face->blend ) ) goto Exit; - /* cannot overflow 32-bit arithmetic because of limits above */ + /* `num_instances' holds the number of all named instances, */ + /* including the default instance which might be missing */ + /* in fvar's table of named instances */ + num_instances = face->root.style_flags >> 16; + + /* cannot overflow 32-bit arithmetic because of the size limits */ + /* used in the `fvar' table validity check in `sfnt_init_face' */ face->blend->mmvar_len = sizeof ( FT_MM_Var ) + fvar_head.axisCount * sizeof ( FT_Var_Axis ) + - fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + - fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + + num_instances * sizeof ( FT_Var_Named_Style ) + + num_instances * fvar_head.axisCount * sizeof ( FT_Fixed ) + 5 * fvar_head.axisCount; if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) @@ -1389,15 +2061,15 @@ /* may have a different number of designs */ /* (or tuples, as called by Apple) */ mmvar->num_namedstyles = - fvar_head.instanceCount; + num_instances; mmvar->axis = (FT_Var_Axis*)&( mmvar[1] ); mmvar->namedstyle = (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] ); next_coords = - (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] ); - for ( i = 0; i < fvar_head.instanceCount; i++ ) + (FT_Fixed*)&( mmvar->namedstyle[num_instances] ); + for ( i = 0; i < num_instances; i++ ) { mmvar->namedstyle[i].coords = next_coords; next_coords += fvar_head.axisCount; @@ -1457,7 +2129,17 @@ FT_TRACE5(( "\n" )); - ns = mmvar->namedstyle; + /* named instance coordinates are stored as design coordinates; */ + /* we have to convert them to normalized coordinates also */ + if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords, + fvar_head.axisCount * num_instances ) ) + goto Exit; + + if ( fvar_head.instanceCount && !face->blend->avar_loaded ) + ft_var_load_avar( face ); + + ns = mmvar->namedstyle; + nsc = face->blend->normalized_stylecoords; for ( i = 0; i < fvar_head.instanceCount; i++, ns++ ) { /* PostScript names add 2 bytes to the instance record size */ @@ -1468,14 +2150,73 @@ ns->strid = FT_GET_USHORT(); (void) /* flags = */ FT_GET_USHORT(); - for ( j = 0; j < fvar_head.axisCount; j++ ) - ns->coords[j] = FT_GET_LONG(); + c = ns->coords; + for ( j = 0; j < fvar_head.axisCount; j++, c++ ) + *c = FT_GET_LONG(); if ( usePsName ) ns->psid = FT_GET_USHORT(); + ft_var_to_normalized( face, + fvar_head.axisCount, + ns->coords, + nsc ); + nsc += fvar_head.axisCount; + FT_FRAME_EXIT(); } + + if ( num_instances != fvar_head.instanceCount ) + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_Int found, dummy1, dummy2; + FT_UInt strid = 0xFFFFFFFFUL; + + + /* the default instance is missing in array the */ + /* of named instances; try to synthesize an entry */ + found = sfnt->get_name_id( face, + TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, + &dummy1, + &dummy2 ); + if ( found ) + strid = TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY; + else + { + found = sfnt->get_name_id( face, + TT_NAME_ID_FONT_SUBFAMILY, + &dummy1, + &dummy2 ); + if ( found ) + strid = TT_NAME_ID_FONT_SUBFAMILY; + } + + if ( found ) + { + found = sfnt->get_name_id( face, + TT_NAME_ID_PS_NAME, + &dummy1, + &dummy2 ); + if ( found ) + { + FT_TRACE5(( "TT_Get_MM_Var:" + " Adding default instance to named instances\n" )); + + ns = &mmvar->namedstyle[fvar_head.instanceCount]; + + ns->strid = strid; + ns->psid = TT_NAME_ID_PS_NAME; + + a = mmvar->axis; + c = ns->coords; + for ( j = 0; j < fvar_head.axisCount; j++, a++, c++ ) + *c = a->def; + } + } + } + + ft_var_load_mvar( face ); } /* fill the output array if requested */ @@ -1512,58 +2253,34 @@ if ( a->tag == TTAG_wght ) a->name = (char*)"Weight"; else if ( a->tag == TTAG_wdth ) - a->name = (char*)"Width"; - else if ( a->tag == TTAG_opsz ) - a->name = (char*)"OpticalSize"; - else if ( a->tag == TTAG_slnt ) - a->name = (char*)"Slant"; - - next_name += 5; - a++; - } - - *master = mmvar; - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Set_MM_Blend */ - /* */ - /* <Description> */ - /* Set the blend (normalized) coordinates for this instance of the */ - /* font. Check that the `gvar' table is reasonable and does some */ - /* initial preparation. */ - /* */ - /* <InOut> */ - /* face :: The font. */ - /* Initialize the blend structure with `gvar' data. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available coordinates. If it is */ - /* larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use the default value (0) for the remaining axes. */ - /* */ - /* coords :: An array of `num_coords', each between [-1,1]. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + a->name = (char*)"Width"; + else if ( a->tag == TTAG_opsz ) + a->name = (char*)"OpticalSize"; + else if ( a->tag == TTAG_slnt ) + a->name = (char*)"Slant"; + + next_name += 5; + a++; + } + + *master = mmvar; + } + + Exit: + return error; + } + + + static FT_Error + tt_set_mm_blend( TT_Face face, FT_UInt num_coords, - FT_Fixed* coords ) + FT_Fixed* coords, + FT_Bool set_design_coords ) { FT_Error error = FT_Err_Ok; GX_Blend blend; FT_MM_Var* mmvar; - FT_UInt i; + FT_UInt i, j; FT_Bool is_default_instance = 1; FT_Memory memory = face->root.memory; @@ -1589,7 +2306,8 @@ if ( num_coords > mmvar->num_axis ) { - FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n", + FT_TRACE2(( "TT_Set_MM_Blend:" + " only using first %d of %d coordinates\n", mmvar->num_axis, num_coords )); num_coords = mmvar->num_axis; } @@ -1614,10 +2332,16 @@ FT_TRACE5(( "\n" )); - if ( !face->isCFF2 && !blend->glyphoffsets ) + if ( !face->is_cff2 && !blend->glyphoffsets ) if ( FT_SET_ERROR( ft_var_load_gvar( face ) ) ) goto Exit; + if ( !blend->coords ) + { + if ( FT_NEW_ARRAY( blend->coords, mmvar->num_axis ) ) + goto Exit; + } + if ( !blend->normalizedcoords ) { if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) ) @@ -1662,6 +2386,12 @@ coords, num_coords * sizeof ( FT_Fixed ) ); + if ( set_design_coords ) + ft_var_to_design( face, + num_coords, + blend->normalizedcoords, + blend->coords ); + face->doblend = TRUE; if ( face->cvt ) @@ -1689,13 +2419,75 @@ } } + /* check whether the current variation tuple coincides */ + /* with a named instance */ + + for ( i = 0; i < blend->mmvar->num_namedstyles; i++ ) + { + FT_Fixed* nsc = blend->normalized_stylecoords + i * blend->num_axis; + FT_Fixed* ns = blend->normalizedcoords; + + + for ( j = 0; j < blend->num_axis; j++, nsc++, ns++ ) + { + if ( *nsc != *ns ) + break; + } + + if ( j == blend->num_axis ) + break; + } + + /* adjust named instance index */ + face->root.face_index &= 0xFFFF; + if ( i < blend->mmvar->num_namedstyles ) + face->root.face_index |= ( i + 1 ) << 16; + face->is_default_instance = is_default_instance; + /* enforce recomputation of the PostScript name; */ + FT_FREE( face->postscript_name ); + face->postscript_name = NULL; + Exit: return error; } + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Set_MM_Blend */ + /* */ + /* <Description> */ + /* Set the blend (normalized) coordinates for this instance of the */ + /* font. Check that the `gvar' table is reasonable and does some */ + /* initial preparation. */ + /* */ + /* <InOut> */ + /* face :: The font. */ + /* Initialize the blend structure with `gvar' data. */ + /* */ + /* <Input> */ + /* num_coords :: The number of available coordinates. If it is */ + /* larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use the default value (0) for the remaining axes. */ + /* */ + /* coords :: An array of `num_coords', each between [-1,1]. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Set_MM_Blend( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + return tt_set_mm_blend( face, num_coords, coords, 1 ); + } + + /*************************************************************************/ /* */ /* <Function> */ @@ -1740,7 +2532,8 @@ nc = num_coords; if ( num_coords > blend->num_axis ) { - FT_TRACE2(( "TT_Get_MM_Blend: only using first %d of %d coordinates\n", + FT_TRACE2(( "TT_Get_MM_Blend:" + " only using first %d of %d coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -1793,14 +2586,16 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = FT_Err_Ok; - FT_Fixed* normalized = NULL; - GX_Blend blend; - FT_MM_Var* mmvar; - FT_UInt i, j; - FT_Var_Axis* a; - GX_AVarSegment av; - FT_Memory memory = face->root.memory; + FT_Error error = FT_Err_Ok; + GX_Blend blend; + FT_MM_Var* mmvar; + FT_UInt i; + FT_Memory memory = face->root.memory; + + FT_Var_Axis* a; + FT_Fixed* c; + + FT_Fixed* normalized = NULL; if ( !face->blend ) @@ -1820,83 +2615,30 @@ num_coords = mmvar->num_axis; } - /* Axis normalization is a two-stage process. First we normalize */ - /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ - /* Then, if there's an `avar' table, we renormalize this range. */ - - if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) - goto Exit; - - FT_TRACE5(( "design coordinates:\n" )); - - a = mmvar->axis; - for ( i = 0; i < num_coords; i++, a++ ) + if ( !blend->coords ) { - FT_Fixed coord = coords[i]; - - - FT_TRACE5(( " %.5f\n", coord / 65536.0 )); - if ( coord > a->maximum || coord < a->minimum ) - { - FT_TRACE1(( - "TT_Set_Var_Design: design coordinate %.5f\n" - " is out of range [%.5f;%.5f]; clamping\n", - coord / 65536.0, - a->minimum / 65536.0, - a->maximum / 65536.0 )); - - if ( coord > a->maximum) - coord = a->maximum; - else - coord = a->minimum; - } - - if ( coord < a->def ) - normalized[i] = -FT_DivFix( coords[i] - a->def, - a->minimum - a->def ); - else if ( coord > a->def ) - normalized[i] = FT_DivFix( coords[i] - a->def, - a->maximum - a->def ); - else - normalized[i] = 0; + if ( FT_NEW_ARRAY( blend->coords, mmvar->num_axis ) ) + goto Exit; } - FT_TRACE5(( "\n" )); - - for ( ; i < mmvar->num_axis; i++ ) - normalized[i] = 0; + FT_MEM_COPY( blend->coords, + coords, + num_coords * sizeof ( FT_Fixed ) ); - if ( !blend->avar_checked ) - ft_var_load_avar( face ); + a = mmvar->axis + num_coords; + c = coords + num_coords; + for ( i = num_coords; i < mmvar->num_axis; i++, a++, c++ ) + *c = a->def; - if ( blend->avar_segment ) - { - FT_TRACE5(( "normalized design coordinates" - " before applying `avar' data:\n" )); + if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) + goto Exit; - av = blend->avar_segment; - for ( i = 0; i < mmvar->num_axis; i++, av++ ) - { - for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) - { - if ( normalized[i] < av->correspondence[j].fromCoord ) - { - FT_TRACE5(( " %.5f\n", normalized[i] / 65536.0 )); + if ( !face->blend->avar_loaded ) + ft_var_load_avar( face ); - normalized[i] = - FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord ) + - av->correspondence[j - 1].toCoord; - break; - } - } - } - } + ft_var_to_normalized( face, num_coords, coords, normalized ); - error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized ); + error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 ); Exit: FT_FREE( normalized ); @@ -1932,12 +2674,8 @@ FT_Fixed* coords ) { FT_Error error = FT_Err_Ok; - - GX_Blend blend; - FT_MM_Var* mmvar; - FT_Var_Axis* a; - - FT_UInt i, j, nc; + GX_Blend blend; + FT_UInt i, nc; if ( !face->blend ) @@ -1951,7 +2689,8 @@ nc = num_coords; if ( num_coords > blend->num_axis ) { - FT_TRACE2(( "TT_Get_Var_Design: only using first %d of %d coordinates\n", + FT_TRACE2(( "TT_Get_Var_Design:" + " only using first %d of %d coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -1959,7 +2698,7 @@ if ( face->doblend ) { for ( i = 0; i < nc; i++ ) - coords[i] = blend->normalizedcoords[i]; + coords[i] = blend->coords[i]; } else { @@ -1970,53 +2709,6 @@ for ( ; i < num_coords; i++ ) coords[i] = 0; - if ( !blend->avar_checked ) - ft_var_load_avar( face ); - - if ( blend->avar_segment ) - { - GX_AVarSegment av = blend->avar_segment; - - - FT_TRACE5(( "design coordinates" - " after removing `avar' distortion:\n" )); - - for ( i = 0; i < nc; i++, av++ ) - { - for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) - { - if ( coords[i] < av->correspondence[j].toCoord ) - { - coords[i] = - FT_MulDiv( coords[i] - av->correspondence[j - 1].toCoord, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord, - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord ) + - av->correspondence[j - 1].fromCoord; - - FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 )); - break; - } - } - } - } - - mmvar = blend->mmvar; - a = mmvar->axis; - - for ( i = 0; i < nc; i++, a++ ) - { - if ( coords[i] < 0 ) - coords[i] = a->def + FT_MulFix( coords[i], - a->def - a->minimum ); - else if ( coords[i] > 0 ) - coords[i] = a->def + FT_MulFix( coords[i], - a->maximum - a->def ); - else - coords[i] = a->def; - } - return FT_Err_Ok; } @@ -2389,25 +3081,12 @@ d1 = out1 - in1; d2 = out2 - in2; - if ( out1 == out2 || in1 == in2 ) - { - for ( p = p1; p <= p2; p++ ) - { - out = in_points[p].x; - - if ( out <= in1 ) - out += d1; - else if ( out >= in2 ) - out += d2; - else - out = out1; - - out_points[p].x = out; - } - } - else + /* If the reference points have the same coordinate but different */ + /* delta, inferred delta is zero. Otherwise interpolate. */ + if ( in1 != in2 || out1 == out2 ) { - FT_Fixed scale = FT_DivFix( out2 - out1, in2 - in1 ); + FT_Fixed scale = in1 != in2 ? FT_DivFix( out2 - out1, in2 - in1 ) + : 0; for ( p = p1; p <= p2; p++ ) @@ -2902,16 +3581,19 @@ tt_get_var_blend( TT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { if ( face->blend ) { if ( num_coords ) - *num_coords = face->blend->num_axis; + *num_coords = face->blend->num_axis; if ( coords ) - *coords = face->blend->normalizedcoords; + *coords = face->blend->coords; + if ( normalizedcoords ) + *normalizedcoords = face->blend->normalizedcoords; if ( mm_var ) - *mm_var = face->blend->mmvar; + *mm_var = face->blend->mmvar; } else { @@ -2927,6 +3609,35 @@ } + static void + ft_var_done_item_variation_store( TT_Face face, + GX_ItemVarStore itemStore ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_UInt i; + + + if ( itemStore->varData ) + { + for ( i = 0; i < itemStore->dataCount; i++ ) + { + FT_FREE( itemStore->varData[i].regionIndices ); + FT_FREE( itemStore->varData[i].deltaSet ); + } + + FT_FREE( itemStore->varData ); + } + + if ( itemStore->varRegionList ) + { + for ( i = 0; i < itemStore->regionCount; i++ ) + FT_FREE( itemStore->varRegionList[i].axisList ); + + FT_FREE( itemStore->varRegionList ); + } + } + + /*************************************************************************/ /* */ /* <Function> */ @@ -2950,7 +3661,9 @@ /* blend->num_axis might not be set up yet */ num_axes = blend->mmvar->num_axis; + FT_FREE( blend->coords ); FT_FREE( blend->normalizedcoords ); + FT_FREE( blend->normalized_stylecoords ); FT_FREE( blend->mmvar ); if ( blend->avar_segment ) @@ -2962,35 +3675,45 @@ if ( blend->hvar_table ) { - if ( blend->hvar_table->itemStore.varData ) - { - for ( i = 0; i < blend->hvar_table->itemStore.dataCount; i++ ) - { - FT_FREE( blend->hvar_table->itemStore.varData[i].regionIndices ); - FT_FREE( blend->hvar_table->itemStore.varData[i].deltaSet ); - } - FT_FREE( blend->hvar_table->itemStore.varData ); - } - - if ( blend->hvar_table->itemStore.varRegionList ) - { - for ( i = 0; i < blend->hvar_table->itemStore.regionCount; i++ ) - FT_FREE( blend->hvar_table->itemStore.varRegionList[i].axisList ); - FT_FREE( blend->hvar_table->itemStore.varRegionList ); - } + ft_var_done_item_variation_store( face, + &blend->hvar_table->itemStore ); FT_FREE( blend->hvar_table->widthMap.innerIndex ); FT_FREE( blend->hvar_table->widthMap.outerIndex ); FT_FREE( blend->hvar_table ); } + if ( blend->vvar_table ) + { + ft_var_done_item_variation_store( face, + &blend->vvar_table->itemStore ); + + FT_FREE( blend->vvar_table->widthMap.innerIndex ); + FT_FREE( blend->vvar_table->widthMap.outerIndex ); + FT_FREE( blend->vvar_table ); + } + + if ( blend->mvar_table ) + { + ft_var_done_item_variation_store( face, + &blend->mvar_table->itemStore ); + + FT_FREE( blend->mvar_table->values ); + FT_FREE( blend->mvar_table ); + } + FT_FREE( blend->tuplecoords ); FT_FREE( blend->glyphoffsets ); FT_FREE( blend ); } } -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ +#else /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_gxvar_dummy; + +#endif /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* END */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttgxvar.h b/Source/ThirdParty/FreeType/src/truetype/ttgxvar.h index 215e109cc6..7e81719a3e 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttgxvar.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttgxvar.h @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader (specification) */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2017 by */ /* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -61,7 +61,7 @@ FT_BEGIN_HEADER } GX_AVarSegmentRec, *GX_AVarSegment; - typedef struct GX_HVarDataRec_ + typedef struct GX_ItemVarDataRec_ { FT_UInt itemCount; /* number of delta sets per item */ FT_UInt regionIdxCount; /* number of region indices in this data */ @@ -70,7 +70,7 @@ FT_BEGIN_HEADER FT_Short* deltaSet; /* array of `itemCount' deltas */ /* use `innerIndex' for this array */ - } GX_HVarDataRec, *GX_HVarData; + } GX_ItemVarDataRec, *GX_ItemVarData; /* contribution of one axis to a region */ @@ -83,53 +83,128 @@ FT_BEGIN_HEADER } GX_AxisCoordsRec, *GX_AxisCoords; - typedef struct GX_HVarRegionRec_ + typedef struct GX_VarRegionRec_ { GX_AxisCoords axisList; /* array of axisCount records */ - } GX_HVarRegionRec, *GX_HVarRegion; + } GX_VarRegionRec, *GX_VarRegion; - /* HVAR item variation store */ - typedef struct GX_HVStoreRec_ + /* item variation store */ + typedef struct GX_ItemVarStoreRec_ { - FT_UInt dataCount; - GX_HVarData varData; /* array of dataCount records; */ - /* use `outerIndex' for this array */ - FT_UShort axisCount; - FT_UInt regionCount; /* total number of regions defined */ - GX_HVarRegion varRegionList; + FT_UInt dataCount; + GX_ItemVarData varData; /* array of dataCount records; */ + /* use `outerIndex' for this array */ + FT_UShort axisCount; + FT_UInt regionCount; /* total number of regions defined */ + GX_VarRegion varRegionList; - } GX_HVStoreRec, *GX_HVStore; + } GX_ItemVarStoreRec, *GX_ItemVarStore; - typedef struct GX_WidthMapRec_ + typedef struct GX_DeltaSetIdxMapRec_ { FT_UInt mapCount; FT_UInt* outerIndex; /* indices to item var data */ FT_UInt* innerIndex; /* indices to delta set */ - } GX_WidthMapRec, *GX_WidthMap; + } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap; /*************************************************************************/ /* */ /* <Struct> */ - /* GX_HVarTableRec */ + /* GX_HVVarTableRec */ /* */ /* <Description> */ - /* Data from the `HVAR' table. */ + /* Data from either the `HVAR' or `VVAR' table. */ /* */ - typedef struct GX_HVarTableRec_ + typedef struct GX_HVVarTableRec_ { - GX_HVStoreRec itemStore; /* Item Variation Store */ - GX_WidthMapRec widthMap; /* Advance Width Mapping */ + GX_ItemVarStoreRec itemStore; /* Item Variation Store */ + GX_DeltaSetIdxMapRec widthMap; /* Advance Width Mapping */ + #if 0 - GX_LSBMap LsbMap; /* not implemented */ - GX_RSBMap RsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec lsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec rsbMap; /* not implemented */ + + GX_DeltaSetIdxMapRec tsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec bsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec vorgMap; /* not implemented */ #endif - } GX_HVarTableRec, *GX_HVarTable; + } GX_HVVarTableRec, *GX_HVVarTable; + + +#define MVAR_TAG_GASP_0 FT_MAKE_TAG( 'g', 's', 'p', '0' ) +#define MVAR_TAG_GASP_1 FT_MAKE_TAG( 'g', 's', 'p', '1' ) +#define MVAR_TAG_GASP_2 FT_MAKE_TAG( 'g', 's', 'p', '2' ) +#define MVAR_TAG_GASP_3 FT_MAKE_TAG( 'g', 's', 'p', '3' ) +#define MVAR_TAG_GASP_4 FT_MAKE_TAG( 'g', 's', 'p', '4' ) +#define MVAR_TAG_GASP_5 FT_MAKE_TAG( 'g', 's', 'p', '5' ) +#define MVAR_TAG_GASP_6 FT_MAKE_TAG( 'g', 's', 'p', '6' ) +#define MVAR_TAG_GASP_7 FT_MAKE_TAG( 'g', 's', 'p', '7' ) +#define MVAR_TAG_GASP_8 FT_MAKE_TAG( 'g', 's', 'p', '8' ) +#define MVAR_TAG_GASP_9 FT_MAKE_TAG( 'g', 's', 'p', '9' ) + +#define MVAR_TAG_CPHT FT_MAKE_TAG( 'c', 'p', 'h', 't' ) +#define MVAR_TAG_HASC FT_MAKE_TAG( 'h', 'a', 's', 'c' ) +#define MVAR_TAG_HCLA FT_MAKE_TAG( 'h', 'c', 'l', 'a' ) +#define MVAR_TAG_HCLD FT_MAKE_TAG( 'h', 'c', 'l', 'd' ) +#define MVAR_TAG_HCOF FT_MAKE_TAG( 'h', 'c', 'o', 'f' ) +#define MVAR_TAG_HCRN FT_MAKE_TAG( 'h', 'c', 'r', 'n' ) +#define MVAR_TAG_HCRS FT_MAKE_TAG( 'h', 'c', 'r', 's' ) +#define MVAR_TAG_HDSC FT_MAKE_TAG( 'h', 'd', 's', 'c' ) +#define MVAR_TAG_HLGP FT_MAKE_TAG( 'h', 'l', 'g', 'p' ) +#define MVAR_TAG_SBXO FT_MAKE_TAG( 's', 'b', 'x', 'o' ) +#define MVAR_TAG_SBXS FT_MAKE_TAG( 's', 'b', 'x', 's' ) +#define MVAR_TAG_SBYO FT_MAKE_TAG( 's', 'b', 'y', 'o' ) +#define MVAR_TAG_SBYS FT_MAKE_TAG( 's', 'b', 'y', 's' ) +#define MVAR_TAG_SPXO FT_MAKE_TAG( 's', 'p', 'x', 'o' ) +#define MVAR_TAG_SPXS FT_MAKE_TAG( 's', 'p', 'x', 's' ) +#define MVAR_TAG_SPYO FT_MAKE_TAG( 's', 'p', 'y', 'o' ) +#define MVAR_TAG_SPYS FT_MAKE_TAG( 's', 'p', 'y', 's' ) +#define MVAR_TAG_STRO FT_MAKE_TAG( 's', 't', 'r', 'o' ) +#define MVAR_TAG_STRS FT_MAKE_TAG( 's', 't', 'r', 's' ) +#define MVAR_TAG_UNDO FT_MAKE_TAG( 'u', 'n', 'd', 'o' ) +#define MVAR_TAG_UNDS FT_MAKE_TAG( 'u', 'n', 'd', 's' ) +#define MVAR_TAG_VASC FT_MAKE_TAG( 'v', 'a', 's', 'c' ) +#define MVAR_TAG_VCOF FT_MAKE_TAG( 'v', 'c', 'o', 'f' ) +#define MVAR_TAG_VCRN FT_MAKE_TAG( 'v', 'c', 'r', 'n' ) +#define MVAR_TAG_VCRS FT_MAKE_TAG( 'v', 'c', 'r', 's' ) +#define MVAR_TAG_VDSC FT_MAKE_TAG( 'v', 'd', 's', 'c' ) +#define MVAR_TAG_VLGP FT_MAKE_TAG( 'v', 'l', 'g', 'p' ) +#define MVAR_TAG_XHGT FT_MAKE_TAG( 'x', 'h', 'g', 't' ) + + + typedef struct GX_ValueRec_ + { + FT_ULong tag; + FT_UShort outerIndex; + FT_UShort innerIndex; + + FT_Short unmodified; /* values are either FT_Short or FT_UShort */ + + } GX_ValueRec, *GX_Value; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* GX_MVarTableRec */ + /* */ + /* <Description> */ + /* Data from the `MVAR' table. */ + /* */ + typedef struct GX_MVarTableRec_ + { + FT_UShort valueCount; + + GX_ItemVarStoreRec itemStore; /* Item Variation Store */ + GX_Value values; /* Value Records */ + + } GX_MVarTableRec, *GX_MVarTable; /*************************************************************************/ @@ -139,37 +214,120 @@ FT_BEGIN_HEADER /* */ /* <Description> */ /* Data for interpolating a font from a distortable font specified */ - /* by the GX *var tables ([fgca]var). */ + /* by the GX *var tables ([fgcahvm]var). */ /* */ /* <Fields> */ - /* num_axis :: The number of axes along which interpolation */ - /* may happen */ + /* num_axis :: */ + /* The number of axes along which interpolation may happen. */ + /* */ + /* coords :: */ + /* An array of design coordinates (in user space) indicating the */ + /* contribution along each axis to the final interpolated font. */ + /* `normalizedcoords' holds the same values. */ + /* */ + /* normalizedcoords :: */ + /* An array of normalized values (between [-1,1]) indicating the */ + /* contribution along each axis to the final interpolated font. */ + /* `coords' holds the same values. */ + /* */ + /* mmvar :: */ + /* Data from the `fvar' table. */ + /* */ + /* mmvar_len :: */ + /* The length of the `mmvar' structure. */ + /* */ + /* normalized_stylecoords :: */ + /* A two-dimensional array that holds the named instance data from */ + /* `mmvar' as normalized values. */ + /* */ + /* avar_loaded :: */ + /* A Boolean; if set, FreeType tried to load (and parse) the `avar' */ + /* table. */ + /* */ + /* avar_segment :: */ + /* Data from the `avar' table. */ /* */ - /* normalizedcoords :: A normalized value (between [-1,1]) indicating */ - /* the contribution along each axis to the final */ - /* interpolated font. */ + /* hvar_loaded :: */ + /* A Boolean; if set, FreeType tried to load (and parse) the `hvar' */ + /* table. */ + /* */ + /* hvar_checked :: */ + /* A Boolean; if set, FreeType successfully loaded and parsed the */ + /* `hvar' table. */ + /* */ + /* hvar_error :: */ + /* If loading and parsing of the `hvar' table failed, this field */ + /* holds the corresponding error code. */ + /* */ + /* hvar_table :: */ + /* Data from the `hvar' table. */ + /* */ + /* vvar_loaded :: */ + /* A Boolean; if set, FreeType tried to load (and parse) the `vvar' */ + /* table. */ + /* */ + /* vvar_checked :: */ + /* A Boolean; if set, FreeType successfully loaded and parsed the */ + /* `vvar' table. */ + /* */ + /* vvar_error :: */ + /* If loading and parsing of the `vvar' table failed, this field */ + /* holds the corresponding error code. */ + /* */ + /* vvar_table :: */ + /* Data from the `vvar' table. */ + /* */ + /* mvar_table :: */ + /* Data from the `mvar' table. */ + /* */ + /* tuplecount :: */ + /* The number of shared tuples in the `gvar' table. */ + /* */ + /* tuplecoords :: */ + /* A two-dimensional array that holds the shared tuple coordinates */ + /* in the `gvar' table. */ + /* */ + /* gv_glyphcnt :: */ + /* The number of glyphs handled in the `gvar' table. */ + /* */ + /* glyphoffsets :: */ + /* Offsets into the glyph variation data array. */ + /* */ + /* gvar_size :: */ + /* The size of the `gvar' table. */ /* */ typedef struct GX_BlendRec_ { FT_UInt num_axis; + FT_Fixed* coords; FT_Fixed* normalizedcoords; FT_MM_Var* mmvar; FT_Offset mmvar_len; - FT_Bool avar_checked; - GX_AVarSegment avar_segment; + FT_Fixed* normalized_stylecoords; + /* normalized_stylecoords[num_namedstyles][num_axis] */ + + FT_Bool avar_loaded; + GX_AVarSegment avar_segment; /* avar_segment[num_axis] */ FT_Bool hvar_loaded; FT_Bool hvar_checked; FT_Error hvar_error; - GX_HVarTable hvar_table; + GX_HVVarTable hvar_table; - FT_UInt tuplecount; /* shared tuples in `gvar' */ - FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ + FT_Bool vvar_loaded; + FT_Bool vvar_checked; + FT_Error vvar_error; + GX_HVVarTable vvar_table; + + GX_MVarTable mvar_table; + + FT_UInt tuplecount; + FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ FT_UInt gv_glyphcnt; - FT_ULong* glyphoffsets; + FT_ULong* glyphoffsets; /* glyphoffsets[gv_glyphcnt + 1] */ FT_ULong gvar_size; @@ -259,10 +417,19 @@ FT_BEGIN_HEADER FT_UInt gindex, FT_Int *adelta ); + FT_LOCAL( FT_Error ) + tt_vadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *adelta ); + + FT_LOCAL( void ) + tt_apply_mvar( TT_Face face ); + FT_LOCAL( FT_Error ) tt_get_var_blend( TT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) diff --git a/Source/ThirdParty/FreeType/src/truetype/ttinterp.c b/Source/ThirdParty/FreeType/src/truetype/ttinterp.c index 4a506ee816..af31408cbf 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttinterp.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -402,7 +402,7 @@ exec->IDefs = size->instruction_defs; exec->pointSize = size->point_size; exec->tt_metrics = size->ttmetrics; - exec->metrics = size->metrics; + exec->metrics = *size->metrics; exec->maxFunc = size->max_func; exec->maxIns = size->max_ins; @@ -1656,7 +1656,7 @@ /* zone :: The affected glyph zone. */ /* */ /* <Note> */ - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* `Touches' the point. */ /* */ static void @@ -1684,7 +1684,7 @@ /* Exception to the post-IUP curfew: Allow the x component of */ /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ /* diagonal stems like on `Z' and `z' post-IUP. */ - if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility ) + if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); else #endif @@ -1700,10 +1700,10 @@ if ( v != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) ) + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) ) #endif zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); @@ -1756,7 +1756,7 @@ /* */ /* The following versions are used whenever both vectors are both */ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* */ /*************************************************************************/ @@ -1774,7 +1774,7 @@ #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility ) + if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) zone->cur[point].x += distance; else #endif @@ -1796,7 +1796,7 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && + exc->backward_compatibility && exc->iupx_called && exc->iupy_called ) ) #endif zone->cur[point].y += distance; @@ -3564,6 +3564,13 @@ #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + /* FDEF is only allowed in `prep' or `fpgm' */ + if ( exc->curRange == tt_coderange_glyph ) + { + exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); + return; + } + /* some font programs are broken enough to redefine functions! */ /* We will then parse the current table. */ @@ -3990,6 +3997,13 @@ TT_DefRecord* limit; + /* we enable IDEF only in `prep' or `fpgm' */ + if ( exc->curRange == tt_coderange_glyph ) + { + exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); + return; + } + /* First of all, look for the same function in our table */ def = exc->IDefs; @@ -5112,11 +5126,11 @@ #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* Native ClearType fonts sign a waiver that turns off all backwards */ + /* Native ClearType fonts sign a waiver that turns off all backward */ /* compatibility hacks and lets them program points to the grid like */ /* it's 1996. They might sign a waiver for just one glyph, though. */ if ( SUBPIXEL_HINTING_MINIMAL ) - exc->backwards_compatibility = !FT_BOOL( L == 4 ); + exc->backward_compatibility = !FT_BOOL( L == 4 ); #endif } } @@ -5204,11 +5218,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) goto Fail; #endif @@ -5259,11 +5273,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) return; #endif @@ -5297,11 +5311,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) return; #endif @@ -5364,7 +5378,7 @@ } - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ static void Move_Zp2_Point( TT_ExecContext exc, FT_UShort point, @@ -5375,8 +5389,8 @@ if ( exc->GS.freeVector.x != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) ) + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) ) #endif exc->zp2.cur[point].x += dx; @@ -5387,10 +5401,10 @@ if ( exc->GS.freeVector.y != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) ) + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) ) #endif exc->zp2.cur[point].y += dy; @@ -5687,14 +5701,14 @@ else #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) { /* Special case: allow SHPIX to move points in the twilight zone. */ /* Otherwise, treat SHPIX the same as DELTAP. Unbreaks various */ /* fonts such as older versions of Rokkitt and DTL Argo T Light */ - /* that would glitch severly after calling ALIGNRP after a blocked */ - /* SHPIX. */ + /* that would glitch severely after calling ALIGNRP after a */ + /* blocked SHPIX. */ if ( in_twilight || ( !( exc->iupx_called && exc->iupy_called ) && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || @@ -6452,7 +6466,7 @@ R.x = FT_MulDiv( val, dax, discriminant ); R.y = FT_MulDiv( val, day, discriminant ); - /* XXX: Block in backwards_compatibility and/or post-IUP? */ + /* XXX: Block in backward_compatibility and/or post-IUP? */ exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x; exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y; } @@ -6460,7 +6474,7 @@ { /* else, take the middle of the middles of A and B */ - /* XXX: Block in backwards_compatibility and/or post-IUP? */ + /* XXX: Block in backward_compatibility and/or post-IUP? */ exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x + exc->zp1.cur[a1].x + exc->zp0.cur[b0].x + @@ -6852,11 +6866,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* Allow IUP until it has been called on both axes. Immediately */ /* return on subsequent ones. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) { if ( exc->iupx_called && exc->iupy_called ) return; @@ -7098,10 +7112,10 @@ { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility */ - /* mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) + /* See `ttinterp.h' for details on backward compatibility */ + /* mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) { if ( !( exc->iupx_called && exc->iupy_called ) && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || @@ -7245,7 +7259,7 @@ { if ( exc->ignore_x_mode ) { - /* if in ClearType backwards compatibility mode, */ + /* if in ClearType backward compatibility mode, */ /* we sometimes change the TrueType version dynamically */ K = exc->rasterizer_version; FT_TRACE6(( "Setting rasterizer version %d\n", @@ -7575,15 +7589,15 @@ #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* Toggle backwards compatibility according to what font says, except */ + /* Toggle backward compatibility according to what font says, except */ /* when it's a `tricky' font that heavily relies on the interpreter to */ - /* render glyphs correctly, e.g. DFKai-SB. Backwards compatibility */ + /* render glyphs correctly, e.g. DFKai-SB. Backward compatibility */ /* hacks may break it. */ if ( SUBPIXEL_HINTING_MINIMAL && !FT_IS_TRICKY( &exc->face->root ) ) - exc->backwards_compatibility = !( exc->GS.instruct_control & 4 ); + exc->backward_compatibility = !( exc->GS.instruct_control & 4 ); else - exc->backwards_compatibility = FALSE; + exc->backward_compatibility = FALSE; exc->iupx_called = FALSE; exc->iupy_called = FALSE; @@ -7605,21 +7619,35 @@ exc->twilight.n_points = (FT_UShort)num_twilight_points; } - /* Set up loop detectors. We restrict the number of LOOPCALL loops */ - /* and the number of JMPR, JROT, and JROF calls with a negative */ - /* argument to values that depend on the size of the CVT table and */ - /* the number of points in the current glyph (if applicable). */ - /* */ - /* The idea is that in real-world bytecode you either iterate over */ - /* all CVT entries, or over all points (or contours) of a glyph, and */ - /* such iterations don't happen very often. */ + /* Set up loop detectors. We restrict the number of LOOPCALL loops */ + /* and the number of JMPR, JROT, and JROF calls with a negative */ + /* argument to values that depend on various parameters like the */ + /* size of the CVT table or the number of points in the current */ + /* glyph (if applicable). */ + /* */ + /* The idea is that in real-world bytecode you either iterate over */ + /* all CVT entries (in the `prep' table), or over all points (or */ + /* contours, in the `glyf' table) of a glyph, and such iterations */ + /* don't happen very often. */ exc->loopcall_counter = 0; exc->neg_jump_counter = 0; /* The maximum values are heuristic. */ - exc->loopcall_counter_max = FT_MAX( 100, - 10 * ( exc->pts.n_points + - exc->cvtSize ) ); + if ( exc->pts.n_points ) + exc->loopcall_counter_max = FT_MAX( 50, + 10 * exc->pts.n_points ) + + FT_MAX( 50, + exc->cvtSize / 10 ); + else + exc->loopcall_counter_max = FT_MAX( 100, + 10 * exc->cvtSize ); + + /* as a protection against an unreasonable number of CVT entries */ + /* we assume at most 100 control values per glyph for the counter */ + if ( exc->loopcall_counter_max > + 100 * (FT_ULong)exc->face->root.num_glyphs ) + exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs; + FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL" " to %d\n", exc->loopcall_counter_max )); @@ -8394,23 +8422,18 @@ exc->error = FT_THROW( Code_Overflow ); LErrorLabel_: - /* If any errors have occurred, function tables may be broken. */ - /* Force a re-execution of `prep' and `fpgm' tables if no */ - /* bytecode debugger is run. */ - if ( exc->error && - !exc->instruction_trap && - exc->curRange == tt_coderange_glyph ) - { + if ( exc->error && !exc->instruction_trap ) FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error )); - exc->size->bytecode_ready = -1; - exc->size->cvt_ready = -1; - } return exc->error; } +#else /* !TT_USE_BYTECODE_INTERPRETER */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_interp_dummy; -#endif /* TT_USE_BYTECODE_INTERPRETER */ +#endif /* !TT_USE_BYTECODE_INTERPRETER */ /* END */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttinterp.h b/Source/ThirdParty/FreeType/src/truetype/ttinterp.h index 33a9b122f0..55e472091c 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttinterp.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -256,7 +256,7 @@ FT_BEGIN_HEADER * Modern TrueType fonts are usually rendered through Microsoft's * collection of rendering techniques called ClearType (e.g., subpixel * rendering and subpixel hinting). When ClearType was introduced, most - * fonts were not ready. Microsoft decided to implement a backwards + * fonts were not ready. Microsoft decided to implement a backward * compatibility mode that employed several simple to complicated * assumptions and tricks that modified the interpretation of the * bytecode contained in these fonts to make them look ClearType-y @@ -316,12 +316,12 @@ FT_BEGIN_HEADER * very specific patterns (`superhinting') for pre-ClearType-displays, * the worse the results. * - * Microsoft defines a way to turn off backwards compatibility and + * Microsoft defines a way to turn off backward compatibility and * interpret instructions as before (called `native ClearType')[2][3]. * The font designer then regains full control and is responsible for * making the font work correctly with ClearType without any * hand-holding by the interpreter or rasterizer[4]. The v40 - * interpreter assumes backwards compatibility by default, which can be + * interpreter assumes backward compatibility by default, which can be * turned off the same way by executing the following in the control * program (cf. `Ins_INSTCTRL'). * @@ -331,7 +331,7 @@ FT_BEGIN_HEADER * [1] Tricky fonts as FreeType defines them rely on the bytecode * interpreter to display correctly. Hacks can interfere with them, * so they get treated like native ClearType fonts (v40 with - * backwards compatibility turned off). Cf. `TT_RunIns'. + * backward compatibility turned off). Cf. `TT_RunIns'. * * [2] Proposed by Microsoft's Greg Hitchcock in * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx @@ -357,10 +357,10 @@ FT_BEGIN_HEADER /* is managed differently. */ FT_Bool vertical_lcd_lean; - /* Default to backwards compatibility mode in v40 interpreter. If */ + /* Default to backward compatibility mode in v40 interpreter. If */ /* this is false, it implies the interpreter is in v35 or in native */ /* ClearType mode. */ - FT_Bool backwards_compatibility; + FT_Bool backward_compatibility; /* Useful for detecting and denying post-IUP trickery that is usually */ /* used to fix pixel patterns (`superhinting'). */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttobjs.c b/Source/ThirdParty/FreeType/src/truetype/ttobjs.c index 7e37113f92..4db0f289f8 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttobjs.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ /* */ /* Objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -147,20 +147,43 @@ { #define TRICK_NAMES_MAX_CHARACTERS 19 -#define TRICK_NAMES_COUNT 9 +#define TRICK_NAMES_COUNT 18 static const char trick_names[TRICK_NAMES_COUNT] [TRICK_NAMES_MAX_CHARACTERS + 1] = { + /* + PostScript names are given in brackets if they differ from the + family name. The version numbers, together with the copyright or + release year data, are taken from fonts available to the + developers. + + Note that later versions of the fonts might be no longer tricky; + for example, `MingLiU' version 7.00 (file `mingliu.ttc' from + Windows 7) is an ordinary TTC with non-tricky subfonts. + */ + + "cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */ + "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */ "DFKaiSho-SB", /* dfkaisb.ttf */ "DFKaiShu", - "DFKai-SB", /* kaiu.ttf */ + "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */ + "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */ + /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */ + "DLCHayMedium", /* dftt-b5.ttf; version 1.00, 1993 */ + "DLCHayBold", /* dftt-b7.ttf; version 1.00, 1993 */ + "DLCKaiMedium", /* dftt-k5.ttf; version 1.00, 1992 */ + "DLCLiShu", /* dftt-l5.ttf; version 1.00, 1992 */ + "DLCRoundBold", /* dftt-r7.ttf; version 1.00, 1993 */ "HuaTianKaiTi?", /* htkt2.ttf */ "HuaTianSongTi?", /* htst3.ttf */ - "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */ - "MingLiU", /* mingliu.ttf & mingliu.ttc */ - "PMingLiU", /* mingliu.ttc */ - "MingLi43", /* mingli.ttf */ + "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */ + /* iicore.ttf; version 0.07, 2007 [Ming] */ + "MingLiU", /* mingliu.ttf */ + /* mingliu.ttc; version 3.21, 2001 */ + "MingMedium", /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */ + "PMingLiU", /* mingliu.ttc; version 3.21, 2001 */ + "MingLi43", /* mingli.ttf; version 1.00, 1992 */ }; int nn; @@ -242,7 +265,7 @@ tt_check_trickyness_sfnt_ids( TT_Face face ) { #define TRICK_SFNT_IDS_PER_FACE 3 -#define TRICK_SFNT_IDS_NUM_FACES 18 +#define TRICK_SFNT_IDS_NUM_FACES 19 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] [TRICK_SFNT_IDS_PER_FACE] = { @@ -266,7 +289,7 @@ { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */ { 0x13A42602UL, 0x0000007EUL } /* prep */ }, - { /* DFKaiShu2 */ + { /* DFKaiShu, variant */ { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */ { 0x13A42602UL, 0x0000007EUL } /* prep */ @@ -340,6 +363,11 @@ { 0x00000000UL, 0x00000000UL }, /* cvt */ { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */ { 0x3900DED3UL, 0x00001E18UL } /* prep */ + }, + { /* MINGLI.TTF, 1992 */ + { 0x00170003UL, 0x00000060UL }, /* cvt */ + { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */ + { 0xD643482AUL, 0x00000035UL } /* prep */ } }; @@ -536,6 +564,7 @@ goto Exit; /* check that we have a valid TrueType file */ + FT_TRACE2(( " " )); error = sfnt->init_face( stream, face, face_index, num_params, params ); /* Stream may have changed. */ @@ -663,6 +692,8 @@ named_style->coords ); if ( error ) goto Exit; + + tt_apply_mvar( face ); } } } @@ -789,14 +820,14 @@ exec->pedantic_hinting = pedantic; { - FT_Size_Metrics* metrics = &exec->metrics; - TT_Size_Metrics* tt_metrics = &exec->tt_metrics; + FT_Size_Metrics* size_metrics = &exec->metrics; + TT_Size_Metrics* tt_metrics = &exec->tt_metrics; - metrics->x_ppem = 0; - metrics->y_ppem = 0; - metrics->x_scale = 0; - metrics->y_scale = 0; + size_metrics->x_ppem = 0; + size_metrics->y_ppem = 0; + size_metrics->x_scale = 0; + size_metrics->y_scale = 0; tt_metrics->ppem = 0; tt_metrics->scale = 0; @@ -819,6 +850,11 @@ FT_TRACE4(( "Executing `fpgm' table.\n" )); error = face->interpreter( exec ); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( error ) + FT_TRACE4(( " interpretation failed with error code 0x%x\n", + error )); +#endif } else error = FT_Err_Ok; @@ -882,8 +918,12 @@ TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); FT_TRACE4(( "Executing `prep' table.\n" )); - error = face->interpreter( exec ); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( error ) + FT_TRACE4(( " interpretation failed with error code 0x%x\n", + error )); +#endif } else error = FT_Err_Ok; @@ -1002,17 +1042,17 @@ /* Set default metrics */ { - TT_Size_Metrics* metrics = &size->ttmetrics; + TT_Size_Metrics* tt_metrics = &size->ttmetrics; - metrics->rotated = FALSE; - metrics->stretched = FALSE; + tt_metrics->rotated = FALSE; + tt_metrics->stretched = FALSE; /* set default engine compensation */ - metrics->compensations[0] = 0; /* gray */ - metrics->compensations[1] = 0; /* black */ - metrics->compensations[2] = 0; /* white */ - metrics->compensations[3] = 0; /* reserved */ + tt_metrics->compensations[0] = 0; /* gray */ + tt_metrics->compensations[1] = 0; /* black */ + tt_metrics->compensations[2] = 0; /* white */ + tt_metrics->compensations[3] = 0; /* reserved */ } /* allocate function defs, instruction defs, cvt, and storage area */ @@ -1075,8 +1115,10 @@ if ( size->bytecode_ready < 0 ) error = tt_size_init_bytecode( (FT_Size)size, pedantic ); + else + error = size->bytecode_ready; - if ( error || size->bytecode_ready ) + if ( error ) goto Exit; /* rescale CVT when needed */ @@ -1108,6 +1150,8 @@ error = tt_size_run_prep( size, pedantic ); } + else + error = size->cvt_ready; Exit: return error; @@ -1184,26 +1228,32 @@ /* have been changed. */ /* */ /* <Input> */ - /* size :: A handle to the target size object. */ + /* size :: A handle to the target size object. */ + /* */ + /* only_height :: Only recompute ascender, descender, and height. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_size_reset( TT_Size size ) + tt_size_reset( TT_Size size, + FT_Bool only_height ) { TT_Face face; - FT_Error error = FT_Err_Ok; - FT_Size_Metrics* metrics; + FT_Size_Metrics* size_metrics; - size->ttmetrics.valid = FALSE; - face = (TT_Face)size->root.face; - metrics = &size->metrics; + /* nothing to do for CFF2 */ + if ( face->is_cff2 ) + return FT_Err_Ok; + + size->ttmetrics.valid = FALSE; + + size_metrics = &size->hinted_metrics; /* copy the result from base layer */ - *metrics = size->root.metrics; + *size_metrics = size->root.metrics; - if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 ) return FT_THROW( Invalid_PPem ); /* This bit flag, if set, indicates that the ppems must be */ @@ -1212,48 +1262,62 @@ /* */ if ( face->header.Flags & 8 ) { - metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, - face->root.units_per_EM ); - metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, - face->root.units_per_EM ); - - metrics->ascender = - FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); - metrics->descender = - FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); - metrics->height = - FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); - metrics->max_advance = - FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, - metrics->x_scale ) ); + /* the TT spec always asks for ROUND, not FLOOR or CEIL */ + size_metrics->ascender = FT_PIX_ROUND( + FT_MulFix( face->root.ascender, + size_metrics->y_scale ) ); + size_metrics->descender = FT_PIX_ROUND( + FT_MulFix( face->root.descender, + size_metrics->y_scale ) ); + size_metrics->height = FT_PIX_ROUND( + FT_MulFix( face->root.height, + size_metrics->y_scale ) ); + } + + size->ttmetrics.valid = TRUE; + + if ( only_height ) + return FT_Err_Ok; + + if ( face->header.Flags & 8 ) + { + /* base scaling values on integer ppem values, */ + /* as mandated by the TrueType specification */ + size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, + face->root.units_per_EM ); + size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, + face->root.units_per_EM ); + + size_metrics->max_advance = FT_PIX_ROUND( + FT_MulFix( face->root.max_advance_width, + size_metrics->x_scale ) ); } /* compute new transformation */ - if ( metrics->x_ppem >= metrics->y_ppem ) + if ( size_metrics->x_ppem >= size_metrics->y_ppem ) { - size->ttmetrics.scale = metrics->x_scale; - size->ttmetrics.ppem = metrics->x_ppem; + size->ttmetrics.scale = size_metrics->x_scale; + size->ttmetrics.ppem = size_metrics->x_ppem; size->ttmetrics.x_ratio = 0x10000L; - size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, - metrics->x_ppem ); + size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem, + size_metrics->x_ppem ); } else { - size->ttmetrics.scale = metrics->y_scale; - size->ttmetrics.ppem = metrics->y_ppem; - size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, - metrics->y_ppem ); + size->ttmetrics.scale = size_metrics->y_scale; + size->ttmetrics.ppem = size_metrics->y_ppem; + size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem, + size_metrics->y_ppem ); size->ttmetrics.y_ratio = 0x10000L; } + size->metrics = size_metrics; + #ifdef TT_USE_BYTECODE_INTERPRETER size->cvt_ready = -1; #endif /* TT_USE_BYTECODE_INTERPRETER */ - if ( !error ) - size->ttmetrics.valid = TRUE; - - return error; + return FT_Err_Ok; } diff --git a/Source/ThirdParty/FreeType/src/truetype/ttobjs.h b/Source/ThirdParty/FreeType/src/truetype/ttobjs.h index 98ad383736..cdacee75e5 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttobjs.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ /* */ /* Objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -278,7 +278,8 @@ FT_BEGIN_HEADER /* we have our own copy of metrics so that we can modify */ /* it without affecting auto-hinting (when used) */ - FT_Size_Metrics metrics; + FT_Size_Metrics* metrics; /* for the current rendering mode */ + FT_Size_Metrics hinted_metrics; /* for the hinted rendering mode */ TT_Size_Metrics ttmetrics; @@ -389,7 +390,8 @@ FT_BEGIN_HEADER #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size ); + tt_size_reset( TT_Size size, + FT_Bool only_height ); /*************************************************************************/ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttpic.c b/Source/ThirdParty/FreeType/src/truetype/ttpic.c index 54a5b8bed6..66bd7e1934 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttpic.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttpic.h b/Source/ThirdParty/FreeType/src/truetype/ttpic.h index a71d589df0..1410cd73c3 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttpic.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2017 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttpload.c b/Source/ThirdParty/FreeType/src/truetype/ttpload.c index d756d38429..70ac15da4a 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttpload.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttpload.c @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttpload.h b/Source/ThirdParty/FreeType/src/truetype/ttpload.h index aa2e38e6e7..79079f345a 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttpload.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttpload.h @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttsubpix.c b/Source/ThirdParty/FreeType/src/truetype/ttsubpix.c index 03950960a4..1c8cf01109 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttsubpix.c +++ b/Source/ThirdParty/FreeType/src/truetype/ttsubpix.c @@ -4,7 +4,7 @@ /* */ /* TrueType Subpixel Hinting. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,7 +27,8 @@ #include "ttsubpix.h" -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY +#if defined( TT_USE_BYTECODE_INTERPRETER ) && \ + defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY ) /*************************************************************************/ /* */ @@ -905,7 +906,7 @@ { TT_Face face = loader->face; FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics.x_ppem; + FT_UInt ppem = loader->size->metrics->x_ppem; FT_String* style = face->root.style_name; @@ -1000,12 +1001,14 @@ } } -#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ +#else /* !(TT_USE_BYTECODE_INTERPRETER && */ + /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ /* ANSI C doesn't like empty source files */ typedef int _tt_subpix_dummy; -#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ +#endif /* !(TT_USE_BYTECODE_INTERPRETER && */ + /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ /* END */ diff --git a/Source/ThirdParty/FreeType/src/truetype/ttsubpix.h b/Source/ThirdParty/FreeType/src/truetype/ttsubpix.h index 86844da666..c68f97ff07 100644 --- a/Source/ThirdParty/FreeType/src/truetype/ttsubpix.h +++ b/Source/ThirdParty/FreeType/src/truetype/ttsubpix.h @@ -4,7 +4,7 @@ /* */ /* TrueType Subpixel Hinting. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1afm.c b/Source/ThirdParty/FreeType/src/type1/t1afm.c index 5c7f389682..11a2646fc2 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1afm.c +++ b/Source/ThirdParty/FreeType/src/type1/t1afm.c @@ -4,7 +4,7 @@ /* */ /* AFM support for Type 1 fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,6 +24,8 @@ #include "t1errors.h" +#ifndef T1_CONFIG_OPTION_NO_AFM + /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ @@ -402,5 +404,12 @@ return FT_Err_Ok; } +#else /* T1_CONFIG_OPTION_NO_AFM */ + + /* ANSI C doesn't like empty source files */ + typedef int _t1_afm_dummy; + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + /* END */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1afm.h b/Source/ThirdParty/FreeType/src/type1/t1afm.h index 3a864f2379..9f62cd013d 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1afm.h +++ b/Source/ThirdParty/FreeType/src/type1/t1afm.h @@ -4,7 +4,7 @@ /* */ /* AFM support for Type 1 fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1driver.c b/Source/ThirdParty/FreeType/src/type1/t1driver.c index fd9e13e11a..c2089947f9 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1driver.c +++ b/Source/ThirdParty/FreeType/src/type1/t1driver.c @@ -4,7 +4,7 @@ /* */ /* Type 1 driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1driver.h b/Source/ThirdParty/FreeType/src/type1/t1driver.h index 78d8e38aa9..292786448d 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1driver.h +++ b/Source/ThirdParty/FreeType/src/type1/t1driver.h @@ -4,7 +4,7 @@ /* */ /* High-level Type 1 driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1errors.h b/Source/ThirdParty/FreeType/src/type1/t1errors.h index 9ba470ed6c..492dbb4a42 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1errors.h +++ b/Source/ThirdParty/FreeType/src/type1/t1errors.h @@ -4,7 +4,7 @@ /* */ /* Type 1 error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1gload.c b/Source/ThirdParty/FreeType/src/type1/t1gload.c index ea36f64142..aaf19b6dcc 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1gload.c +++ b/Source/ThirdParty/FreeType/src/type1/t1gload.c @@ -4,7 +4,7 @@ /* */ /* Type 1 Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1gload.h b/Source/ThirdParty/FreeType/src/type1/t1gload.h index 975f227853..cc4d5e734f 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1gload.h +++ b/Source/ThirdParty/FreeType/src/type1/t1gload.h @@ -4,7 +4,7 @@ /* */ /* Type 1 Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1load.c b/Source/ThirdParty/FreeType/src/type1/t1load.c index f6b43dc2f6..f5c661f7de 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1load.c +++ b/Source/ThirdParty/FreeType/src/type1/t1load.c @@ -4,7 +4,7 @@ /* */ /* Type 1 font loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1load.h b/Source/ThirdParty/FreeType/src/type1/t1load.h index 72445c531b..2d86984f0e 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1load.h +++ b/Source/ThirdParty/FreeType/src/type1/t1load.h @@ -4,7 +4,7 @@ /* */ /* Type 1 font loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1objs.c b/Source/ThirdParty/FreeType/src/type1/t1objs.c index a009117133..97c16b0fdf 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1objs.c +++ b/Source/ThirdParty/FreeType/src/type1/t1objs.c @@ -4,7 +4,7 @@ /* */ /* Type 1 objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -49,9 +49,6 @@ /* */ /* SIZE FUNCTIONS */ /* */ - /* note that we store the global hints in the size's "internal" root */ - /* field */ - /* */ /*************************************************************************/ @@ -77,16 +74,16 @@ T1_Size size = (T1_Size)t1size; - if ( size->root.internal ) + if ( t1size->internal->module_data ) { PSH_Globals_Funcs funcs; funcs = T1_Size_Get_Globals_Funcs( size ); if ( funcs ) - funcs->destroy( (PSH_Globals)size->root.internal ); + funcs->destroy( (PSH_Globals)t1size->internal->module_data ); - size->root.internal = NULL; + t1size->internal->module_data = NULL; } } @@ -108,7 +105,7 @@ error = funcs->create( size->root.face->memory, &face->type1.private_dict, &globals ); if ( !error ) - size->root.internal = (FT_Size_Internal)(void*)globals; + t1size->internal->module_data = globals; } return error; @@ -126,7 +123,7 @@ FT_Request_Metrics( size->root.face, req ); if ( funcs ) - funcs->set_scale( (PSH_Globals)size->root.internal, + funcs->set_scale( (PSH_Globals)t1size->internal->module_data, size->root.metrics.x_scale, size->root.metrics.y_scale, 0, 0 ); diff --git a/Source/ThirdParty/FreeType/src/type1/t1objs.h b/Source/ThirdParty/FreeType/src/type1/t1objs.h index 94fbdee9ae..39d26bf8b9 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1objs.h +++ b/Source/ThirdParty/FreeType/src/type1/t1objs.h @@ -4,7 +4,7 @@ /* */ /* Type 1 objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1parse.c b/Source/ThirdParty/FreeType/src/type1/t1parse.c index 478c80bce3..18dd26434c 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1parse.c +++ b/Source/ThirdParty/FreeType/src/type1/t1parse.c @@ -4,7 +4,7 @@ /* */ /* Type 1 parser (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1parse.h b/Source/ThirdParty/FreeType/src/type1/t1parse.h index affa818e63..3396680d1a 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1parse.h +++ b/Source/ThirdParty/FreeType/src/type1/t1parse.h @@ -4,7 +4,7 @@ /* */ /* Type 1 parser (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/t1tokens.h b/Source/ThirdParty/FreeType/src/type1/t1tokens.h index a84f291a6b..ca0c55f903 100644 --- a/Source/ThirdParty/FreeType/src/type1/t1tokens.h +++ b/Source/ThirdParty/FreeType/src/type1/t1tokens.h @@ -4,7 +4,7 @@ /* */ /* Type 1 tokenizer (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type1/type1.c b/Source/ThirdParty/FreeType/src/type1/type1.c index bb8aca97f9..81795376ef 100644 --- a/Source/ThirdParty/FreeType/src/type1/type1.c +++ b/Source/ThirdParty/FreeType/src/type1/type1.c @@ -4,7 +4,7 @@ /* */ /* FreeType Type 1 driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,17 +17,14 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "t1parse.c" -#include "t1load.c" -#include "t1objs.c" -#include "t1driver.c" -#include "t1gload.c" -#ifndef T1_CONFIG_OPTION_NO_AFM #include "t1afm.c" -#endif +#include "t1driver.c" +#include "t1gload.c" +#include "t1load.c" +#include "t1objs.c" +#include "t1parse.c" /* END */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42drivr.c b/Source/ThirdParty/FreeType/src/type42/t42drivr.c index dad35c2b11..366cfb3a1d 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42drivr.c +++ b/Source/ThirdParty/FreeType/src/type42/t42drivr.c @@ -4,7 +4,7 @@ /* */ /* High-level Type 42 driver interface (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42drivr.h b/Source/ThirdParty/FreeType/src/type42/t42drivr.h index 6ddfb639d5..1ac4a0a1a1 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42drivr.h +++ b/Source/ThirdParty/FreeType/src/type42/t42drivr.h @@ -4,7 +4,7 @@ /* */ /* High-level Type 42 driver interface (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42error.h b/Source/ThirdParty/FreeType/src/type42/t42error.h index e1097cc81e..fda92abf57 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42error.h +++ b/Source/ThirdParty/FreeType/src/type42/t42error.h @@ -4,7 +4,7 @@ /* */ /* Type 42 error codes (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42objs.c b/Source/ThirdParty/FreeType/src/type42/t42objs.c index 1e4907b86f..87e5206b7f 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42objs.c +++ b/Source/ThirdParty/FreeType/src/type42/t42objs.c @@ -4,7 +4,7 @@ /* */ /* Type 42 objects manager (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42objs.h b/Source/ThirdParty/FreeType/src/type42/t42objs.h index 87a40452f4..eb4c5bf69f 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42objs.h +++ b/Source/ThirdParty/FreeType/src/type42/t42objs.h @@ -4,7 +4,7 @@ /* */ /* Type 42 objects manager (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42parse.c b/Source/ThirdParty/FreeType/src/type42/t42parse.c index ef36ffe3c6..e7c6770bd2 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42parse.c +++ b/Source/ThirdParty/FreeType/src/type42/t42parse.c @@ -4,7 +4,7 @@ /* */ /* Type 42 font parser (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42parse.h b/Source/ThirdParty/FreeType/src/type42/t42parse.h index ba9e857190..7a68606f2e 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42parse.h +++ b/Source/ThirdParty/FreeType/src/type42/t42parse.h @@ -4,7 +4,7 @@ /* */ /* Type 42 font parser (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/t42types.h b/Source/ThirdParty/FreeType/src/type42/t42types.h index 850a156e45..2306ab6c77 100644 --- a/Source/ThirdParty/FreeType/src/type42/t42types.h +++ b/Source/ThirdParty/FreeType/src/type42/t42types.h @@ -4,7 +4,7 @@ /* */ /* Type 42 font data types (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/type42/type42.c b/Source/ThirdParty/FreeType/src/type42/type42.c index 0d17a9b1dc..ae8ac26782 100644 --- a/Source/ThirdParty/FreeType/src/type42/type42.c +++ b/Source/ThirdParty/FreeType/src/type42/type42.c @@ -4,7 +4,7 @@ /* */ /* FreeType Type 42 driver component. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -15,11 +15,13 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> + +#include "t42drivr.c" #include "t42objs.c" #include "t42parse.c" -#include "t42drivr.c" + /* END */ diff --git a/Source/ThirdParty/FreeType/src/winfonts/fnterrs.h b/Source/ThirdParty/FreeType/src/winfonts/fnterrs.h index 6835d3e64f..4251021a70 100644 --- a/Source/ThirdParty/FreeType/src/winfonts/fnterrs.h +++ b/Source/ThirdParty/FreeType/src/winfonts/fnterrs.h @@ -4,7 +4,7 @@ /* */ /* Win FNT/FON error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/Source/ThirdParty/FreeType/src/winfonts/winfnt.c b/Source/ThirdParty/FreeType/src/winfonts/winfnt.c index 99cc966171..9811fbb05a 100644 --- a/Source/ThirdParty/FreeType/src/winfonts/winfnt.c +++ b/Source/ThirdParty/FreeType/src/winfonts/winfnt.c @@ -4,7 +4,7 @@ /* */ /* FreeType font driver for Windows FNT/FON files */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* Copyright 2003 Huw D M Davies for Codeweavers */ /* Copyright 2007 Dmitry Timoshkov for Codeweavers */ @@ -561,7 +561,7 @@ error = fnt_font_load( face->font, stream ); if ( error ) { - FT_TRACE2(( "font #%lu load error %d\n", + FT_TRACE2(( "font #%lu load error 0x%x\n", dir_entry2.name, error )); goto Fail; } diff --git a/Source/ThirdParty/FreeType/src/winfonts/winfnt.h b/Source/ThirdParty/FreeType/src/winfonts/winfnt.h index 9a4f32d5b0..884b645a2d 100644 --- a/Source/ThirdParty/FreeType/src/winfonts/winfnt.h +++ b/Source/ThirdParty/FreeType/src/winfonts/winfnt.h @@ -4,7 +4,7 @@ /* */ /* FreeType font driver for Windows FNT/FON files */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* Copyright 2007 Dmitry Timoshkov for Codeweavers */ /* */ diff --git a/Source/ThirdParty/LZ4/LICENSE b/Source/ThirdParty/LZ4/LICENSE new file mode 100644 index 0000000000..74c2cdd7d5 --- /dev/null +++ b/Source/ThirdParty/LZ4/LICENSE @@ -0,0 +1,24 @@ +LZ4 Library +Copyright (c) 2011-2016, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +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. diff --git a/Source/ThirdParty/LZ4/lz4.c b/Source/ThirdParty/LZ4/lz4.c index 08cf6b5cd7..143c36e1a7 100644 --- a/Source/ThirdParty/LZ4/lz4.c +++ b/Source/ThirdParty/LZ4/lz4.c @@ -1,6 +1,6 @@ /* LZ4 - Fast LZ compression algorithm - Copyright (C) 2011-2015, Yann Collet. + Copyright (C) 2011-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -28,12 +28,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 */ -/************************************** +/*-************************************ * Tuning parameters **************************************/ /* @@ -41,7 +41,9 @@ * Select how default compression functions will allocate memory for their hash table, * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). */ -#define HEAPMODE 0 +#ifndef HEAPMODE +# define HEAPMODE 0 +#endif /* * ACCELERATION_DEFAULT : @@ -50,9 +52,31 @@ #define ACCELERATION_DEFAULT 1 -/************************************** +/*-************************************ * CPU Feature Detection **************************************/ +/* LZ4_FORCE_MEMORY_ACCESS + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method is portable but violate C standard. + * It can generate buggy code on targets which generate assembly depending on alignment. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define LZ4_FORCE_MEMORY_ACCESS 2 +# elif defined(__INTEL_COMPILER) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) +# define LZ4_FORCE_MEMORY_ACCESS 1 +# endif +#endif + /* * LZ4_FORCE_SW_BITCOUNT * Define this parameter if your target system or compiler does not support hardware bit count @@ -62,13 +86,14 @@ #endif -/************************************** -* Includes +/*-************************************ +* Dependency **************************************/ #include "lz4.h" +/* see also "memory routines" below */ -/************************************** +/*-************************************ * Compiler Options **************************************/ #ifdef _MSC_VER /* Visual Studio */ @@ -77,19 +102,16 @@ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ # pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ #else -# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ -# if defined(__GNUC__) || defined(__clang__) -# define FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define FORCE_INLINE static inline -# endif +# if defined(__GNUC__) || defined(__clang__) +# define FORCE_INLINE static inline __attribute__((always_inline)) +# elif defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define FORCE_INLINE static inline # else # define FORCE_INLINE static -# endif /* __STDC_VERSION__ */ +# endif #endif /* _MSC_VER */ -/* LZ4_GCC_VERSION is defined into lz4.h */ -#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) # define expect(expr,value) (__builtin_expect ((expr),(value)) ) #else # define expect(expr,value) (expr) @@ -99,7 +121,7 @@ #define unlikely(expr) expect((expr) != 0, 0) -/************************************** +/*-************************************ * Memory routines **************************************/ #include <stdlib.h> /* malloc, calloc, free */ @@ -109,54 +131,100 @@ #define MEM_INIT memset -/************************************** +/*-************************************ * Basic Types **************************************/ -#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # include <stdint.h> typedef uint8_t BYTE; typedef uint16_t U16; typedef uint32_t U32; typedef int32_t S32; typedef uint64_t U64; + typedef uintptr_t uptrval; #else typedef unsigned char BYTE; typedef unsigned short U16; typedef unsigned int U32; typedef signed int S32; typedef unsigned long long U64; + typedef size_t uptrval; /* generally true, except OpenVMS-64 */ #endif +#if defined(__x86_64__) + typedef U64 reg_t; /* 64-bits in x32 mode */ +#else + typedef size_t reg_t; /* 32-bits in x32 mode */ +#endif -/************************************** +/*-************************************ * Reading and writing into memory **************************************/ -#define STEPSIZE sizeof(size_t) - -static unsigned LZ4_64bits(void) { return sizeof(void*)==8; } - static unsigned LZ4_isLittleEndian(void) { - const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ return one.c[0]; } +#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) +/* lie to the compiler about data alignment; use with caution */ + +static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } +static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } +static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } + +static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } +static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } + +#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; + +static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } +static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } +static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } + +static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } +static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } + +#else /* safe and portable access through memcpy() */ + static U16 LZ4_read16(const void* memPtr) { - U16 val16; - memcpy(&val16, memPtr, 2); - return val16; + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U32 LZ4_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static reg_t LZ4_read_ARCH(const void* memPtr) +{ + reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static void LZ4_write16(void* memPtr, U16 value) +{ + memcpy(memPtr, &value, sizeof(value)); } +static void LZ4_write32(void* memPtr, U32 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +#endif /* LZ4_FORCE_MEMORY_ACCESS */ + + static U16 LZ4_readLE16(const void* memPtr) { - if (LZ4_isLittleEndian()) - { + if (LZ4_isLittleEndian()) { return LZ4_read16(memPtr); - } - else - { + } else { const BYTE* p = (const BYTE*)memPtr; return (U16)((U16)p[0] + (p[1]<<8)); } @@ -164,63 +232,39 @@ static U16 LZ4_readLE16(const void* memPtr) static void LZ4_writeLE16(void* memPtr, U16 value) { - if (LZ4_isLittleEndian()) - { - memcpy(memPtr, &value, 2); - } - else - { + if (LZ4_isLittleEndian()) { + LZ4_write16(memPtr, value); + } else { BYTE* p = (BYTE*)memPtr; p[0] = (BYTE) value; p[1] = (BYTE)(value>>8); } } -static U32 LZ4_read32(const void* memPtr) +static void LZ4_copy8(void* dst, const void* src) { - U32 val32; - memcpy(&val32, memPtr, 4); - return val32; + memcpy(dst,src,8); } -static U64 LZ4_read64(const void* memPtr) -{ - U64 val64; - memcpy(&val64, memPtr, 8); - return val64; -} - -static size_t LZ4_read_ARCH(const void* p) -{ - if (LZ4_64bits()) - return (size_t)LZ4_read64(p); - else - return (size_t)LZ4_read32(p); -} - - -static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); } - -static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); } - -/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */ +/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; - BYTE* e = (BYTE*)dstEnd; + BYTE* const e = (BYTE*)dstEnd; + do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e); } -/************************************** +/*-************************************ * Common Constants **************************************/ #define MINMATCH 4 -#define COPYLENGTH 8 +#define WILDCOPYLENGTH 8 #define LASTLITERALS 5 -#define MFLIMIT (COPYLENGTH+MINMATCH) +#define MFLIMIT (WILDCOPYLENGTH+MINMATCH) static const int LZ4_minLength = (MFLIMIT+1); #define KB *(1 <<10) @@ -236,55 +280,48 @@ static const int LZ4_minLength = (MFLIMIT+1); #define RUN_MASK ((1U<<RUN_BITS)-1) -/************************************** +/*-************************************ * Common Utils **************************************/ #define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ -/************************************** +/*-************************************ * Common functions **************************************/ -static unsigned LZ4_NbCommonBytes (register size_t val) +static unsigned LZ4_NbCommonBytes (register reg_t val) { - if (LZ4_isLittleEndian()) - { - if (LZ4_64bits()) - { + if (LZ4_isLittleEndian()) { + if (sizeof(val)==8) { # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanForward64( &r, (U64)val ); return (int)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctzll((U64)val) >> 3); # else static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; # endif - } - else /* 32 bits */ - { + } else /* 32 bits */ { # if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r; _BitScanForward( &r, (U32)val ); return (int)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctz((U32)val) >> 3); # else static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; # endif } - } - else /* Big Endian CPU */ - { - if (LZ4_64bits()) - { + } else /* Big Endian CPU */ { + if (sizeof(val)==8) { # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse64( &r, val ); return (unsigned)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clzll((U64)val) >> 3); # else unsigned r; @@ -293,14 +330,12 @@ static unsigned LZ4_NbCommonBytes (register size_t val) r += (!val); return r; # endif - } - else /* 32 bits */ - { + } else /* 32 bits */ { # if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse( &r, (unsigned long)val ); return (unsigned)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clz((U32)val) >> 3); # else unsigned r; @@ -312,19 +347,19 @@ static unsigned LZ4_NbCommonBytes (register size_t val) } } +#define STEPSIZE sizeof(reg_t) static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) { const BYTE* const pStart = pIn; - while (likely(pIn<pInLimit-(STEPSIZE-1))) - { - size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); + while (likely(pIn<pInLimit-(STEPSIZE-1))) { + reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } pIn += LZ4_NbCommonBytes(diff); return (unsigned)(pIn - pStart); } - if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } + if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++; return (unsigned)(pIn - pStart); @@ -332,29 +367,16 @@ static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLi #ifndef LZ4_COMMONDEFS_ONLY -/************************************** +/*-************************************ * Local Constants **************************************/ -#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) -#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) -#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ - static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1)); static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */ -/************************************** +/*-************************************ * Local Structures and types **************************************/ -typedef struct { - U32 hashTable[HASH_SIZE_U32]; - U32 currentOffset; - U32 initCheck; - const BYTE* dictionary; - BYTE* bufferStart; /* obsolete, used for slideInputBuffer */ - U32 dictSize; -} LZ4_stream_t_internal; - typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; typedef enum { byPtr, byU32, byU16 } tableType_t; @@ -365,44 +387,43 @@ typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; typedef enum { full = 0, partial = 1 } earlyEnd_directive; -/************************************** +/*-************************************ * Local Utils **************************************/ int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } +const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } int LZ4_sizeofState() { return LZ4_STREAMSIZE; } - -/******************************** +/*-****************************** * Compression functions ********************************/ - -static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType) +static U32 LZ4_hash4(U32 sequence, tableType_t const tableType) { if (tableType == byU16) - return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); else - return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); + return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); } -static const U64 prime5bytes = 889523592379ULL; -static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType) +static U32 LZ4_hash5(U64 sequence, tableType_t const tableType) { + static const U64 prime5bytes = 889523592379ULL; + static const U64 prime8bytes = 11400714785074694791ULL; const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; - const U32 hashMask = (1<<hashLog) - 1; - return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask; + if (LZ4_isLittleEndian()) + return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); + else + return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); } -static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType) +FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) { - if (LZ4_64bits()) - return LZ4_hashSequence64(sequence, tableType); - return LZ4_hashSequence((U32)sequence, tableType); + if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); + return LZ4_hash4(LZ4_read32(p), tableType); } -static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); } - static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) { switch (tableType) @@ -413,27 +434,30 @@ static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableTy } } -static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) { - U32 h = LZ4_hashPosition(p, tableType); + U32 const h = LZ4_hashPosition(p, tableType); LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); } static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) { if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } - if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } - { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ + if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } + { const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ } -static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) { - U32 h = LZ4_hashPosition(p, tableType); + U32 const h = LZ4_hashPosition(p, tableType); return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); } + +/** LZ4_compress_generic() : + inlined, to ensure branches are decided at compilation time */ FORCE_INLINE int LZ4_compress_generic( - void* const ctx, + LZ4_stream_t_internal* const cctx, const char* const source, char* const dest, const int inputSize, @@ -444,15 +468,13 @@ FORCE_INLINE int LZ4_compress_generic( const dictIssue_directive dictIssue, const U32 acceleration) { - LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx; - const BYTE* ip = (const BYTE*) source; const BYTE* base; const BYTE* lowLimit; - const BYTE* const lowRefLimit = ip - dictPtr->dictSize; - const BYTE* const dictionary = dictPtr->dictionary; - const BYTE* const dictEnd = dictionary + dictPtr->dictSize; - const size_t dictDelta = dictEnd - (const BYTE*)source; + const BYTE* const lowRefLimit = ip - cctx->dictSize; + const BYTE* const dictionary = cctx->dictionary; + const BYTE* const dictEnd = dictionary + cctx->dictSize; + const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source; const BYTE* anchor = (const BYTE*) source; const BYTE* const iend = ip + inputSize; const BYTE* const mflimit = iend - MFLIMIT; @@ -462,10 +484,9 @@ FORCE_INLINE int LZ4_compress_generic( BYTE* const olimit = op + maxOutputSize; U32 forwardH; - size_t refDelta=0; /* Init conditions */ - if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */ switch(dict) { case noDict: @@ -474,11 +495,11 @@ FORCE_INLINE int LZ4_compress_generic( lowLimit = (const BYTE*)source; break; case withPrefix64k: - base = (const BYTE*)source - dictPtr->currentOffset; - lowLimit = (const BYTE*)source - dictPtr->dictSize; + base = (const BYTE*)source - cctx->currentOffset; + lowLimit = (const BYTE*)source - cctx->dictSize; break; case usingExtDict: - base = (const BYTE*)source - dictPtr->currentOffset; + base = (const BYTE*)source - cctx->currentOffset; lowLimit = (const BYTE*)source; break; } @@ -486,44 +507,38 @@ FORCE_INLINE int LZ4_compress_generic( if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ /* First Byte */ - LZ4_putPosition(ip, ctx, tableType, base); + LZ4_putPosition(ip, cctx->hashTable, tableType, base); ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ - for ( ; ; ) - { + for ( ; ; ) { + ptrdiff_t refDelta = 0; const BYTE* match; BYTE* token; - { - const BYTE* forwardIp = ip; + + /* Find a match */ + { const BYTE* forwardIp = ip; unsigned step = 1; unsigned searchMatchNb = acceleration << LZ4_skipTrigger; - - /* Find a match */ do { - U32 h = forwardH; + U32 const h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if (unlikely(forwardIp > mflimit)) goto _last_literals; - match = LZ4_getPositionOnHash(h, ctx, tableType, base); - if (dict==usingExtDict) - { - if (match<(const BYTE*)source) - { + match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); + if (dict==usingExtDict) { + if (match < (const BYTE*)source) { refDelta = dictDelta; lowLimit = dictionary; - } - else - { + } else { refDelta = 0; lowLimit = (const BYTE*)source; - } - } + } } forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) @@ -531,18 +546,17 @@ FORCE_INLINE int LZ4_compress_generic( } /* Catch up */ - while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } + while (((ip>anchor) & (match+refDelta > lowLimit)) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } - { - /* Encode Literal length */ - unsigned litLength = (unsigned)(ip - anchor); + /* Encode Literals */ + { unsigned const litLength = (unsigned)(ip - anchor); token = op++; - if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) - return 0; /* Check output limit */ - if (litLength>=RUN_MASK) - { + if ((outputLimited) && /* Check output buffer overflow */ + (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) + return 0; + if (litLength >= RUN_MASK) { int len = (int)litLength-RUN_MASK; - *token=(RUN_MASK<<ML_BITS); + *token = (RUN_MASK<<ML_BITS); for(; len >= 255 ; len-=255) *op++ = 255; *op++ = (BYTE)len; } @@ -558,41 +572,37 @@ FORCE_INLINE int LZ4_compress_generic( LZ4_writeLE16(op, (U16)(ip-match)); op+=2; /* Encode MatchLength */ - { - unsigned matchLength; + { unsigned matchCode; - if ((dict==usingExtDict) && (lowLimit==dictionary)) - { + if ((dict==usingExtDict) && (lowLimit==dictionary)) { const BYTE* limit; match += refDelta; limit = ip + (dictEnd-match); if (limit > matchlimit) limit = matchlimit; - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); - ip += MINMATCH + matchLength; - if (ip==limit) - { - unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit); - matchLength += more; + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); + ip += MINMATCH + matchCode; + if (ip==limit) { + unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit); + matchCode += more; ip += more; } - } - else - { - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - ip += MINMATCH + matchLength; + } else { + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); + ip += MINMATCH + matchCode; } - if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit))) - return 0; /* Check output limit */ - if (matchLength>=ML_MASK) - { + if ( outputLimited && /* Check output buffer overflow */ + (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) + return 0; + if (matchCode >= ML_MASK) { *token += ML_MASK; - matchLength -= ML_MASK; - for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; } - if (matchLength >= 255) { matchLength-=255; *op++ = 255; } - *op++ = (BYTE)matchLength; - } - else *token += (BYTE)(matchLength); + matchCode -= ML_MASK; + LZ4_write32(op, 0xFFFFFFFF); + while (matchCode >= 4*255) op+=4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4*255; + op += matchCode / 255; + *op++ = (BYTE)(matchCode % 255); + } else + *token += (BYTE)(matchCode); } anchor = ip; @@ -601,24 +611,19 @@ FORCE_INLINE int LZ4_compress_generic( if (ip > mflimit) break; /* Fill table */ - LZ4_putPosition(ip-2, ctx, tableType, base); + LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); /* Test next position */ - match = LZ4_getPosition(ip, ctx, tableType, base); - if (dict==usingExtDict) - { - if (match<(const BYTE*)source) - { + match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); + if (dict==usingExtDict) { + if (match < (const BYTE*)source) { refDelta = dictDelta; lowLimit = dictionary; - } - else - { + } else { refDelta = 0; lowLimit = (const BYTE*)source; - } - } - LZ4_putPosition(ip, ctx, tableType, base); + } } + LZ4_putPosition(ip, cctx->hashTable, tableType, base); if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) && (match+MAX_DISTANCE>=ip) && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) @@ -630,19 +635,16 @@ FORCE_INLINE int LZ4_compress_generic( _last_literals: /* Encode Last Literals */ - { - const size_t lastRun = (size_t)(iend - anchor); - if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) - return 0; /* Check output limit */ - if (lastRun >= RUN_MASK) - { + { size_t const lastRun = (size_t)(iend - anchor); + if ( (outputLimited) && /* Check output buffer overflow */ + ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) + return 0; + if (lastRun >= RUN_MASK) { size_t accumulator = lastRun - RUN_MASK; *op++ = RUN_MASK << ML_BITS; for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; *op++ = (BYTE) accumulator; - } - else - { + } else { *op++ = (BYTE)(lastRun<<ML_BITS); } memcpy(op, anchor, lastRun); @@ -656,22 +658,20 @@ FORCE_INLINE int LZ4_compress_generic( int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { + LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; LZ4_resetStream((LZ4_stream_t*)state); if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; - if (maxOutputSize >= LZ4_compressBound(inputSize)) - { + if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); - } - else - { + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); + } else { if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); } } @@ -682,10 +682,10 @@ int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutp void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ #else LZ4_stream_t ctx; - void* ctxPtr = &ctx; + void* const ctxPtr = &ctx; #endif - int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + int const result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); #if (HEAPMODE) FREEMEM(ctxPtr); @@ -705,22 +705,21 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t ctx; - LZ4_resetStream(&ctx); if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); } -/******************************** -* destSize variant +/*-****************************** +* *_destSize() variant ********************************/ static int LZ4_compress_destSize_generic( - void* const ctx, + LZ4_stream_t_internal* const ctx, const char* const src, char* const dst, int* const srcSizePtr, @@ -752,32 +751,30 @@ static int LZ4_compress_destSize_generic( /* First Byte */ *srcSizePtr = 0; - LZ4_putPosition(ip, ctx, tableType, base); + LZ4_putPosition(ip, ctx->hashTable, tableType, base); ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ - for ( ; ; ) - { + for ( ; ; ) { const BYTE* match; BYTE* token; - { - const BYTE* forwardIp = ip; + + /* Find a match */ + { const BYTE* forwardIp = ip; unsigned step = 1; unsigned searchMatchNb = 1 << LZ4_skipTrigger; - /* Find a match */ do { U32 h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); - if (unlikely(forwardIp > mflimit)) - goto _last_literals; + if (unlikely(forwardIp > mflimit)) goto _last_literals; - match = LZ4_getPositionOnHash(h, ctx, tableType, base); + match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base); forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base); } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) || (LZ4_read32(match) != LZ4_read32(ip)) ); @@ -786,18 +783,15 @@ static int LZ4_compress_destSize_generic( /* Catch up */ while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } - { - /* Encode Literal length */ - unsigned litLength = (unsigned)(ip - anchor); + /* Encode Literal length */ + { unsigned litLength = (unsigned)(ip - anchor); token = op++; - if (op + ((litLength+240)/255) + litLength > oMaxLit) - { + if (op + ((litLength+240)/255) + litLength > oMaxLit) { /* Not enough space for a last match */ op--; goto _last_literals; } - if (litLength>=RUN_MASK) - { + if (litLength>=RUN_MASK) { unsigned len = litLength - RUN_MASK; *token=(RUN_MASK<<ML_BITS); for(; len >= 255 ; len-=255) *op++ = 255; @@ -815,21 +809,15 @@ static int LZ4_compress_destSize_generic( LZ4_writeLE16(op, (U16)(ip-match)); op+=2; /* Encode MatchLength */ - { - size_t matchLength; + { size_t matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - - if (op + ((matchLength+240)/255) > oMaxMatch) - { + if (op + ((matchLength+240)/255) > oMaxMatch) { /* Match description too long : reduce it */ matchLength = (15-1) + (oMaxMatch-op) * 255; } - //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH); ip += MINMATCH + matchLength; - if (matchLength>=ML_MASK) - { + if (matchLength>=ML_MASK) { *token += ML_MASK; matchLength -= ML_MASK; while (matchLength >= 255) { matchLength-=255; *op++ = 255; } @@ -845,11 +833,11 @@ static int LZ4_compress_destSize_generic( if (op > oMaxSeq) break; /* Fill table */ - LZ4_putPosition(ip-2, ctx, tableType, base); + LZ4_putPosition(ip-2, ctx->hashTable, tableType, base); /* Test next position */ - match = LZ4_getPosition(ip, ctx, tableType, base); - LZ4_putPosition(ip, ctx, tableType, base); + match = LZ4_getPosition(ip, ctx->hashTable, tableType, base); + LZ4_putPosition(ip, ctx->hashTable, tableType, base); if ( (match+MAX_DISTANCE>=ip) && (LZ4_read32(match)==LZ4_read32(ip)) ) { token=op++; *token=0; goto _next_match; } @@ -860,25 +848,20 @@ static int LZ4_compress_destSize_generic( _last_literals: /* Encode Last Literals */ - { - size_t lastRunSize = (size_t)(iend - anchor); - if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) - { + { size_t lastRunSize = (size_t)(iend - anchor); + if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) { /* adapt lastRunSize to fill 'dst' */ lastRunSize = (oend-op) - 1; lastRunSize -= (lastRunSize+240)/255; } ip = anchor + lastRunSize; - if (lastRunSize >= RUN_MASK) - { + if (lastRunSize >= RUN_MASK) { size_t accumulator = lastRunSize - RUN_MASK; *op++ = RUN_MASK << ML_BITS; for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; *op++ = (BYTE) accumulator; - } - else - { + } else { *op++ = (BYTE)(lastRunSize<<ML_BITS); } memcpy(op, anchor, lastRunSize); @@ -891,20 +874,17 @@ static int LZ4_compress_destSize_generic( } -static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) +static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) { - LZ4_resetStream((LZ4_stream_t*)state); + LZ4_resetStream(state); - if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */ - { + if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); - } - else - { + } else { if (*srcSizePtr < LZ4_64Klimit) - return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16); + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16); else - return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr); + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, sizeof(void*)==8 ? byU32 : byPtr); } } @@ -912,10 +892,10 @@ static int LZ4_compress_destSize_extState (void* state, const char* src, char* d int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) { #if (HEAPMODE) - void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ #else LZ4_stream_t ctxBody; - void* ctx = &ctxBody; + LZ4_stream_t* ctx = &ctxBody; #endif int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); @@ -928,7 +908,7 @@ int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targe -/******************************** +/*-****************************** * Streaming functions ********************************/ @@ -952,10 +932,10 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_stream) } -#define HASH_UNIT sizeof(size_t) +#define HASH_UNIT sizeof(reg_t) int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) { - LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; + LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; const BYTE* p = (const BYTE*)dictionary; const BYTE* const dictEnd = p + dictSize; const BYTE* base; @@ -963,8 +943,7 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */ LZ4_resetStream(LZ4_dict); - if (dictSize < (int)HASH_UNIT) - { + if (dictSize < (int)HASH_UNIT) { dict->dictionary = NULL; dict->dictSize = 0; return 0; @@ -977,8 +956,7 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) dict->dictSize = (U32)(dictEnd - p); dict->currentOffset += dict->dictSize; - while (p <= dictEnd-HASH_UNIT) - { + while (p <= dictEnd-HASH_UNIT) { LZ4_putPosition(p, dict->hashTable, byU32, base); p+=3; } @@ -990,14 +968,12 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) { if ((LZ4_dict->currentOffset > 0x80000000) || - ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */ - { + ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) { /* address space overflow */ /* rescale hash table */ - U32 delta = LZ4_dict->currentOffset - 64 KB; + U32 const delta = LZ4_dict->currentOffset - 64 KB; const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; int i; - for (i=0; i<HASH_SIZE_U32; i++) - { + for (i=0; i<LZ4_HASH_SIZE_U32; i++) { if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0; else LZ4_dict->hashTable[i] -= delta; } @@ -1010,7 +986,7 @@ static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { - LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream; + LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse; const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; const BYTE* smallest = (const BYTE*) source; @@ -1020,10 +996,8 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; /* Check overlapping input/dictionary space */ - { - const BYTE* sourceEnd = (const BYTE*) source + inputSize; - if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) - { + { const BYTE* sourceEnd = (const BYTE*) source + inputSize; + if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) { streamPtr->dictSize = (U32)(dictEnd - sourceEnd); if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; @@ -1032,25 +1006,23 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch } /* prefix mode : source data follows dictionary */ - if (dictEnd == (const BYTE*)source) - { + if (dictEnd == (const BYTE*)source) { int result; if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); else - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); streamPtr->dictSize += (U32)inputSize; streamPtr->currentOffset += (U32)inputSize; return result; } /* external dictionary mode */ - { - int result; + { int result; if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); else - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); streamPtr->dictionary = (const BYTE*)source; streamPtr->dictSize = (U32)inputSize; streamPtr->currentOffset += (U32)inputSize; @@ -1062,15 +1034,15 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch /* Hidden debug function, to force external dictionary mode */ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize) { - LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict; + LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; int result; const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; const BYTE* smallest = dictEnd; if (smallest > (const BYTE*) source) smallest = (const BYTE*) source; - LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest); + LZ4_renormDictT(streamPtr, smallest); - result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); streamPtr->dictionary = (const BYTE*)source; streamPtr->dictSize = (U32)inputSize; @@ -1080,10 +1052,17 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* } +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) { - LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; - const BYTE* previousDictEnd = dict->dictionary + dict->dictSize; + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; + const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; @@ -1098,14 +1077,14 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) -/******************************* +/*-***************************** * Decompression functions *******************************/ -/* - * This generic decompression function cover all use cases. - * It shall be instantiated several times, using different sets of directives - * Note that it is essential this generic function is really inlined, - * in order to remove useless branches during compilation optimization. +/*! LZ4_decompress_generic() : + * This generic decompression function cover all use cases. + * It shall be instantiated several times, using different sets of directives + * Note that it is important this generic function is really inlined, + * in order to remove useless branches during compilation optimization. */ FORCE_INLINE int LZ4_decompress_generic( const char* const source, @@ -1117,7 +1096,7 @@ FORCE_INLINE int LZ4_decompress_generic( int partialDecoding, /* full, partial */ int targetOutputSize, /* only used if partialDecoding==partial */ int dict, /* noDict, withPrefix64k, usingExtDict */ - const BYTE* const lowPrefix, /* == dest if dict == noDict */ + const BYTE* const lowPrefix, /* == dest when no prefix */ const BYTE* const dictStart, /* only if dict==usingExtDict */ const size_t dictSize /* note : = 0 if noDict */ ) @@ -1133,53 +1112,45 @@ FORCE_INLINE int LZ4_decompress_generic( const BYTE* const lowLimit = lowPrefix - dictSize; const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; - const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; - const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; + const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; + const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; const int safeDecode = (endOnInput==endOnInputSize); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); /* Special cases */ - if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ + if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); - - /* Main Loop */ - while (1) - { - unsigned token; + /* Main Loop : decode sequences */ + while (1) { size_t length; const BYTE* match; + size_t offset; /* get literal length */ - token = *ip++; - if ((length=(token>>ML_BITS)) == RUN_MASK) - { + unsigned const token = *ip++; + if ((length=(token>>ML_BITS)) == RUN_MASK) { unsigned s; - do - { + do { s = *ip++; length += s; - } - while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255)); - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */ - if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */ + } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) ); + if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error; /* overflow detection */ + if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error; /* overflow detection */ } /* copy literals */ cpy = op+length; - if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) - || ((!endOnInput) && (cpy>oend-COPYLENGTH))) + if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) + || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) { - if (partialDecoding) - { + if (partialDecoding) { if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ - } - else - { + } else { if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ } @@ -1192,84 +1163,76 @@ FORCE_INLINE int LZ4_decompress_generic( ip += length; op = cpy; /* get offset */ - match = cpy - LZ4_readLE16(ip); ip+=2; - if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */ + offset = LZ4_readLE16(ip); ip+=2; + match = op - offset; + if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */ + LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */ /* get matchlength */ length = token & ML_MASK; - if (length == ML_MASK) - { + if (length == ML_MASK) { unsigned s; - do - { - if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; + do { s = *ip++; + if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; length += s; } while (s==255); - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */ + if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ } length += MINMATCH; /* check external dictionary */ - if ((dict==usingExtDict) && (match < lowPrefix)) - { + if ((dict==usingExtDict) && (match < lowPrefix)) { if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ - if (length <= (size_t)(lowPrefix-match)) - { + if (length <= (size_t)(lowPrefix-match)) { /* match can be copied as a single segment from external dictionary */ - match = dictEnd - (lowPrefix-match); - memmove(op, match, length); op += length; - } - else - { - /* match encompass external dictionary and current segment */ - size_t copySize = (size_t)(lowPrefix-match); + memmove(op, dictEnd - (lowPrefix-match), length); + op += length; + } else { + /* match encompass external dictionary and current block */ + size_t const copySize = (size_t)(lowPrefix-match); + size_t const restSize = length - copySize; memcpy(op, dictEnd - copySize, copySize); op += copySize; - copySize = length - copySize; - if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */ - { - BYTE* const endOfMatch = op + copySize; + if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ + BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) *op++ = *copyFrom++; - } - else - { - memcpy(op, lowPrefix, copySize); - op += copySize; - } - } + } else { + memcpy(op, lowPrefix, restSize); + op += restSize; + } } continue; } - /* copy repeated sequence */ + /* copy match within block */ cpy = op + length; - if (unlikely((op-match)<8)) - { - const size_t dec64 = dec64table[op-match]; + if (unlikely(offset<8)) { + const int dec64 = dec64table[offset]; op[0] = match[0]; op[1] = match[1]; op[2] = match[2]; op[3] = match[3]; - match += dec32table[op-match]; - LZ4_copy4(op+4, match); - op += 8; match -= dec64; - } else { LZ4_copy8(op, match); op+=8; match+=8; } - - if (unlikely(cpy>oend-12)) - { - if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */ - if (op < oend-8) - { - LZ4_wildCopy(op, match, oend-8); - match += (oend-8) - op; - op = oend-8; + match += dec32table[offset]; + memcpy(op+4, match, 4); + match -= dec64; + } else { LZ4_copy8(op, match); match+=8; } + op += 8; + + if (unlikely(cpy>oend-12)) { + BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1); + if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ + if (op < oCopyLimit) { + LZ4_wildCopy(op, match, oCopyLimit); + match += oCopyLimit - op; + op = oCopyLimit; } while (op<cpy) *op++ = *match++; + } else { + LZ4_copy8(op, match); + if (length>16) LZ4_wildCopy(op+8, match+8, cpy); } - else - LZ4_wildCopy(op, match, cpy); op=cpy; /* correction */ } @@ -1301,15 +1264,7 @@ int LZ4_decompress_fast(const char* source, char* dest, int originalSize) } -/* streaming decompression functions */ - -typedef struct -{ - const BYTE* externalDict; - size_t extDictSize; - const BYTE* prefixEnd; - size_t prefixSize; -} LZ4_streamDecode_t_internal; +/*===== streaming decompression functions =====*/ /* * If you prefer dynamic allocation methods, @@ -1328,16 +1283,16 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) return 0; } -/* - * LZ4_setStreamDecode - * Use this function to instruct where to find the dictionary +/*! + * LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. * This function is not necessary if previous data is still available where it was decoded. * Loading a size of 0 is allowed (same effect as no dictionary). * Return : 1 if OK, 0 if error */ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) { - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; lz4sd->prefixSize = (size_t) dictSize; lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; lz4sd->externalDict = NULL; @@ -1354,20 +1309,17 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti */ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) { - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixEnd == (BYTE*)dest) - { + if (lz4sd->prefixEnd == (BYTE*)dest) { result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize += result; lz4sd->prefixEnd += result; - } - else - { + } else { lz4sd->extDictSize = lz4sd->prefixSize; lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, @@ -1383,22 +1335,19 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) { - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixEnd == (BYTE*)dest) - { + if (lz4sd->prefixEnd == (BYTE*)dest) { result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize += originalSize; lz4sd->prefixEnd += originalSize; - } - else - { + } else { lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); @@ -1422,8 +1371,7 @@ FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest { if (dictSize==0) return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); - if (dictStart+dictSize == dest) - { + if (dictStart+dictSize == dest) { if (dictSize >= (int)(64 KB - 1)) return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); @@ -1448,7 +1396,7 @@ int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compres } -/*************************************************** +/*=************************************************* * Obsolete Functions ***************************************************/ /* obsolete compression functions */ @@ -1473,29 +1421,29 @@ int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; } -static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base) +static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base) { - MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE); - lz4ds->bufferStart = base; + MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t)); + lz4ds->internal_donotuse.bufferStart = base; } int LZ4_resetStreamState(void* state, char* inputBuffer) { - if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ - LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer); + if ((((uptrval)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ + LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer); return 0; } void* LZ4_create (char* inputBuffer) { - void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64); - LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer); + LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t)); + LZ4_init (lz4ds, (BYTE*)inputBuffer); return lz4ds; } char* LZ4_slideInputBuffer (void* LZ4_Data) { - LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data; + LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)LZ4_Data)->internal_donotuse; int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB); return (char*)(ctx->bufferStart + dictSize); } @@ -1513,4 +1461,3 @@ int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int origin } #endif /* LZ4_COMMONDEFS_ONLY */ - diff --git a/Source/ThirdParty/LZ4/lz4.h b/Source/ThirdParty/LZ4/lz4.h index 3e74002256..0aae19c9a7 100644 --- a/Source/ThirdParty/LZ4/lz4.h +++ b/Source/ThirdParty/LZ4/lz4.h @@ -1,7 +1,7 @@ /* - LZ4 - Fast LZ compression algorithm - Header File - Copyright (C) 2011-2015, Yann Collet. + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -29,34 +29,79 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 */ -#pragma once +#ifndef LZ4_H_2983827168210 +#define LZ4_H_2983827168210 #if defined (__cplusplus) extern "C" { #endif +/* --- Dependency --- */ +#include <stddef.h> /* size_t */ + + +/** + Introduction + + LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core, + scalable with multi-cores CPU. It features an extremely fast decoder, with speed in + multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. + + The LZ4 compression library provides in-memory compression and decompression functions. + Compression can be done in: + - a single step (described as Simple Functions) + - a single step, reusing a context (described in Advanced Functions) + - unbounded multiple steps (described as Streaming compression) + + lz4.h provides block compression functions. It gives full buffer control to user. + Decompressing an lz4-compressed block also requires metadata (such as compressed size). + Each application is free to encode such metadata in whichever way it wants. + + An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md), + take care of encoding standard metadata alongside LZ4-compressed blocks. + If your application requires interoperability, it's recommended to use it. + A library is provided to take care of it, see lz4frame.h. +*/ + +/*^*************************************************************** +* Export parameters +*****************************************************************/ /* - * lz4.h provides block compression functions, and gives full buffer control to programmer. - * If you need to generate inter-operable compressed data (respecting LZ4 frame specification), - * and can let the library handle its own memory, please use lz4frame.h instead. +* LZ4_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL */ +#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) +# define LZ4LIB_API __declspec(dllexport) +#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) +# define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define LZ4LIB_API +#endif -/************************************** -* Version -**************************************/ + +/*========== Version =========== */ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ #define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */ -#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */ +#define LZ4_VERSION_RELEASE 5 /* for tweaks, bug-fixes, or development */ + #define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) -int LZ4_versionNumber (void); -/************************************** +#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE +#define LZ4_QUOTE(str) #str +#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) +#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) + +LZ4LIB_API int LZ4_versionNumber (void); +LZ4LIB_API const char* LZ4_versionString (void); + + +/*-************************************ * Tuning parameter **************************************/ -/* +/*! * LZ4_MEMORY_USAGE : * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) * Increasing memory usage improves compression ratio @@ -66,15 +111,10 @@ int LZ4_versionNumber (void); #define LZ4_MEMORY_USAGE 14 -/************************************** +/*-************************************ * Simple Functions **************************************/ - -int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); -int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); - -/* -LZ4_compress_default() : +/*! LZ4_compress_default() : Compresses 'sourceSize' bytes from buffer 'source' into already allocated 'dest' buffer of size 'maxDestSize'. Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). @@ -86,9 +126,10 @@ LZ4_compress_default() : sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) - or 0 if compression fails + or 0 if compression fails */ +LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); -LZ4_decompress_safe() : +/*! LZ4_decompress_safe() : compressedSize : is the precise full size of the compressed block. maxDecompressedSize : is the size of destination buffer, which must be already allocated. return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) @@ -97,15 +138,16 @@ LZ4_decompress_safe() : This function is protected against buffer overflow exploits, including malicious data packets. It never writes outside output buffer, nor reads outside input buffer. */ +LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); -/************************************** +/*-************************************ * Advanced Functions **************************************/ #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ #define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) -/* +/*! LZ4_compressBound() : Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) This function is primarily useful for memory allocation purposes (destination buffer size). @@ -115,9 +157,9 @@ LZ4_compressBound() : return : maximum output size in a "worst case" scenario or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) */ -int LZ4_compressBound(int inputSize); +LZ4LIB_API int LZ4_compressBound(int inputSize); -/* +/*! LZ4_compress_fast() : Same as LZ4_compress_default(), but allows to select an "acceleration" factor. The larger the acceleration value, the faster the algorithm, but also the lesser the compression. @@ -125,21 +167,21 @@ LZ4_compress_fast() : An acceleration value of "1" is the same as regular LZ4_compress_default() Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1. */ -int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); +LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); -/* +/*! LZ4_compress_fast_extState() : Same compression function, just using an externally allocated memory space to store compression state. Use LZ4_sizeofState() to know how much memory must be allocated, and allocate it on 8-bytes boundaries (using malloc() typically). Then, provide it as 'void* state' to compression function. */ -int LZ4_sizeofState(void); -int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); +LZ4LIB_API int LZ4_sizeofState(void); +LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); -/* +/*! LZ4_compress_destSize() : Reverse the logic, by compressing as much data as possible from 'source' buffer into already allocated buffer 'dest' of size 'targetDestSize'. @@ -150,10 +192,10 @@ LZ4_compress_destSize() : return : Nb bytes written into 'dest' (necessarily <= targetDestSize) or 0 if compression fails */ -int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); +LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); -/* +/*! LZ4_decompress_fast() : originalSize : is the original and therefore uncompressed size return : the number of bytes read from the source buffer (in other words, the compressed size) @@ -164,9 +206,9 @@ LZ4_decompress_fast() : However, it does not provide any protection against intentionally modified data stream (malicious input). Use this function in trusted environment only (data to decode comes from a trusted source). */ -int LZ4_decompress_fast (const char* source, char* dest, int originalSize); +LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize); -/* +/*! LZ4_decompress_safe_partial() : This function decompress a compressed block of size 'compressedSize' at position 'source' into destination buffer 'dest' of size 'maxDecompressedSize'. @@ -178,98 +220,73 @@ LZ4_decompress_safe_partial() : If the source stream is detected malformed, the function will stop decoding and return a negative result. This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets */ -int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); +LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); -/*********************************************** +/*-********************************************* * Streaming Compression Functions ***********************************************/ -#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) -#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long)) -/* - * LZ4_stream_t - * information structure to track an LZ4 stream. - * important : init this structure content before first use ! - * note : only allocated directly the structure if you are statically linking LZ4 - * If you are using liblz4 as a DLL, please use below construction methods instead. - */ -typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t; +typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ -/* - * LZ4_resetStream - * Use this function to init an allocated LZ4_stream_t structure +/*! LZ4_createStream() and LZ4_freeStream() : + * LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure. + * LZ4_freeStream() releases its memory. */ -void LZ4_resetStream (LZ4_stream_t* streamPtr); +LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); +LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); -/* - * LZ4_createStream will allocate and initialize an LZ4_stream_t structure - * LZ4_freeStream releases its memory. - * In the context of a DLL (liblz4), please use these methods rather than the static struct. - * They are more future proof, in case of a change of LZ4_stream_t size. +/*! LZ4_resetStream() : + * An LZ4_stream_t structure can be allocated once and re-used multiple times. + * Use this function to init an allocated `LZ4_stream_t` structure and start a new compression. */ -LZ4_stream_t* LZ4_createStream(void); -int LZ4_freeStream (LZ4_stream_t* streamPtr); +LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); -/* - * LZ4_loadDict - * Use this function to load a static dictionary into LZ4_stream. - * Any previous data will be forgotten, only 'dictionary' will remain in memory. - * Loading a size of 0 is allowed. - * Return : dictionary size, in bytes (necessarily <= 64 KB) +/*! LZ4_loadDict() : + * Use this function to load a static dictionary into LZ4_stream. + * Any previous data will be forgotten, only 'dictionary' will remain in memory. + * Loading a size of 0 is allowed. + * Return : dictionary size, in bytes (necessarily <= 64 KB) */ -int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); - -/* - * LZ4_compress_fast_continue - * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. - * Important : Previous data blocks are assumed to still be present and unmodified ! - * 'dst' buffer must be already allocated. - * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. - * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. +LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/*! LZ4_compress_fast_continue() : + * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. + * Important : Previous data blocks are assumed to still be present and unmodified ! + * 'dst' buffer must be already allocated. + * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. + * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. */ -int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); - -/* - * LZ4_saveDict - * If previously compressed data block is not guaranteed to remain available at its memory location - * save it into a safer place (char* safeBuffer) - * Note : you don't need to call LZ4_loadDict() afterwards, - * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue() - * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error +LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); + +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. */ -int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); +LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); -/************************************************ +/*-********************************************** * Streaming Decompression Functions +* Bufferless synchronous API ************************************************/ +typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */ -#define LZ4_STREAMDECODESIZE_U64 4 -#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) -typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t; -/* - * LZ4_streamDecode_t - * information structure to track an LZ4 stream. - * init this structure content using LZ4_setStreamDecode or memset() before first use ! - * - * In the context of a DLL (liblz4) please prefer usage of construction methods below. - * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future. - * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure - * LZ4_freeStreamDecode releases its memory. - */ -LZ4_streamDecode_t* LZ4_createStreamDecode(void); -int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); +/* creation / destruction of streaming decompression tracking structure */ +LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); +LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); -/* - * LZ4_setStreamDecode - * Use this function to instruct where to find the dictionary. - * Setting a size of 0 is allowed (same effect as reset). - * Return : 1 if OK, 0 if error +/*! LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. + * Setting a size of 0 is allowed (same effect as reset). + * @return : 1 if OK, 0 if error */ -int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); +LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); -/* -*_continue() : +/*! +LZ4_decompress_*_continue() : These decoding functions allow decompression of multiple blocks in "streaming" mode. Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) In the case of a ring buffers, decoding buffer must be either : @@ -285,35 +302,120 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, and indicate where it is saved using LZ4_setStreamDecode() */ -int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); -int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); +LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); +LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); -/* -Advanced decoding functions : -*_usingDict() : - These decoding functions work the same as - a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue() - They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure. -*/ -int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); -int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); +/*! LZ4_decompress_*_usingDict() : + * These decoding functions work the same as + * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() + * They are stand-alone, and don't need an LZ4_streamDecode_t structure. + */ +LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); +LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); + + +/*^********************************************** + * !!!!!! STATIC LINKING ONLY !!!!!! + ***********************************************/ +/*-************************************ + * Private definitions + ************************************** + * Do not use these definitions. + * They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. + * Using these definitions will expose code to API and/or ABI break in future versions of the library. + **************************************/ +#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) +#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) +#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ + +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#include <stdint.h> + +typedef struct { + uint32_t hashTable[LZ4_HASH_SIZE_U32]; + uint32_t currentOffset; + uint32_t initCheck; + const uint8_t* dictionary; + uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */ + uint32_t dictSize; +} LZ4_stream_t_internal; + +typedef struct { + const uint8_t* externalDict; + size_t extDictSize; + const uint8_t* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#else + +typedef struct { + unsigned int hashTable[LZ4_HASH_SIZE_U32]; + unsigned int currentOffset; + unsigned int initCheck; + const unsigned char* dictionary; + unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */ + unsigned int dictSize; +} LZ4_stream_t_internal; + +typedef struct { + const unsigned char* externalDict; + size_t extDictSize; + const unsigned char* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#endif +/*! + * LZ4_stream_t : + * information structure to track an LZ4 stream. + * init this structure before first use. + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) +#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) +union LZ4_stream_u { + unsigned long long table[LZ4_STREAMSIZE_U64]; + LZ4_stream_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_stream_t */ + + +/*! + * LZ4_streamDecode_t : + * information structure to track an LZ4 stream during decompression. + * init this structure using LZ4_setStreamDecode (or memset()) before first use + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMDECODESIZE_U64 4 +#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) +union LZ4_streamDecode_u { + unsigned long long table[LZ4_STREAMDECODESIZE_U64]; + LZ4_streamDecode_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_streamDecode_t */ -/************************************** +/*=************************************ * Obsolete Functions **************************************/ -/* Deprecate Warnings */ -/* Should these warnings messages be a problem, +/* Deprecation warnings */ +/* Should these warnings be a problem, it is generally possible to disable them, - with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual for example. - You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */ -#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK -# define LZ4_DEPRECATE_WARNING_DEFBLOCK + typically with -Wno-deprecated-declarations for gcc + or _CRT_SECURE_NO_WARNINGS in Visual. + Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */ +#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS +# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ +#else # define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -# if (LZ4_GCC_VERSION >= 405) || defined(__clang__) +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define LZ4_DEPRECATED(message) [[deprecated(message)]] +# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__) # define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) # elif (LZ4_GCC_VERSION >= 301) # define LZ4_DEPRECATED(message) __attribute__((deprecated)) @@ -323,20 +425,19 @@ int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalS # pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") # define LZ4_DEPRECATED(message) # endif -#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */ +#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ /* Obsolete compression functions */ -/* These functions are planned to start generate warnings by r131 approximately */ -int LZ4_compress (const char* source, char* dest, int sourceSize); -int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); -int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); -int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); -int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); -int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); /* Obsolete decompression functions */ /* These function names are completely deprecated and must no longer be used. - They are only provided here for compatibility with older programs. + They are only provided in lz4.c for compatibility with older programs. - LZ4_uncompress is the same as LZ4_decompress_fast - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe These function prototypes are now disabled; uncomment them only if you really need them. @@ -358,3 +459,5 @@ LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress #if defined (__cplusplus) } #endif + +#endif /* LZ4_H_2983827168210 */ diff --git a/Source/ThirdParty/LZ4/lz4hc.c b/Source/ThirdParty/LZ4/lz4hc.c index bbe7a9d2d7..5d4ea3e632 100644 --- a/Source/ThirdParty/LZ4/lz4hc.c +++ b/Source/ThirdParty/LZ4/lz4hc.c @@ -1,6 +1,6 @@ /* LZ4 HC - High Compression Mode of LZ4 - Copyright (C) 2011-2015, Yann Collet. + Copyright (C) 2011-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -28,27 +28,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 + - LZ4 source repository : https://github.com/lz4/lz4 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c */ +/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */ - -/************************************** +/* ************************************* * Tuning Parameter -**************************************/ -static const int LZ4HC_compressionLevel_default = 9; +***************************************/ + +/*! + * HEAPMODE : + * Select how default compression function will allocate workplace memory, + * in stack (0:fastest), or in heap (1:requires malloc()). + * Since workplace is rather large, heap mode is recommended. + */ +#ifndef LZ4HC_HEAPMODE +# define LZ4HC_HEAPMODE 1 +#endif -/************************************** -* Includes -**************************************/ +/* ************************************* +* Dependency +***************************************/ #include "lz4hc.h" -/************************************** +/* ************************************* * Local Compiler Options -**************************************/ +***************************************/ #if defined(__GNUC__) # pragma GCC diagnostic ignored "-Wunused-function" #endif @@ -58,52 +67,24 @@ static const int LZ4HC_compressionLevel_default = 9; #endif -/************************************** +/* ************************************* * Common LZ4 definition -**************************************/ +***************************************/ #define LZ4_COMMONDEFS_ONLY #include "lz4.c" -/************************************** +/* ************************************* * Local Constants -**************************************/ -#define DICTIONARY_LOGSIZE 16 -#define MAXD (1<<DICTIONARY_LOGSIZE) -#define MAXD_MASK (MAXD - 1) - -#define HASH_LOG (DICTIONARY_LOGSIZE-1) -#define HASHTABLESIZE (1 << HASH_LOG) -#define HASH_MASK (HASHTABLESIZE - 1) - +***************************************/ #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH) -static const int g_maxCompressionLevel = 16; - - -/************************************** -* Local Types -**************************************/ -typedef struct -{ - U32 hashTable[HASHTABLESIZE]; - U16 chainTable[MAXD]; - const BYTE* end; /* next block here to continue on current prefix */ - const BYTE* base; /* All index relative to this position */ - const BYTE* dictBase; /* alternate base for extDict */ - BYTE* inputBuffer; /* deprecated */ - U32 dictLimit; /* below that point, need extDict */ - U32 lowLimit; /* below that point, no more dict */ - U32 nextToUpdate; /* index from which to continue dictionary update */ - U32 compressionLevel; -} LZ4HC_Data_Structure; - /************************************** * Local Macros **************************************/ -#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG)) -//#define DELTANEXTU16(p) chainTable[(p) & MAXD_MASK] /* flexible, MAXD dependent */ +#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG)) +#define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */ #define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */ static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); } @@ -113,7 +94,7 @@ static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr) /************************************** * HC Compression **************************************/ -static void LZ4HC_init (LZ4HC_Data_Structure* hc4, const BYTE* start) +static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start) { MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable)); MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); @@ -127,21 +108,20 @@ static void LZ4HC_init (LZ4HC_Data_Structure* hc4, const BYTE* start) /* Update chains up to ip (excluded) */ -FORCE_INLINE void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip) +FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip) { - U16* chainTable = hc4->chainTable; - U32* HashTable = hc4->hashTable; + U16* const chainTable = hc4->chainTable; + U32* const hashTable = hc4->hashTable; const BYTE* const base = hc4->base; - const U32 target = (U32)(ip - base); + U32 const target = (U32)(ip - base); U32 idx = hc4->nextToUpdate; - while(idx < target) - { - U32 h = LZ4HC_hashPtr(base+idx); - size_t delta = idx - HashTable[h]; + while (idx < target) { + U32 const h = LZ4HC_hashPtr(base+idx); + size_t delta = idx - hashTable[h]; if (delta>MAX_DISTANCE) delta = MAX_DISTANCE; DELTANEXTU16(idx) = (U16)delta; - HashTable[h] = idx; + hashTable[h] = idx; idx++; } @@ -149,7 +129,7 @@ FORCE_INLINE void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip) } -FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, /* Index table will be updated */ +FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4, /* Index table will be updated */ const BYTE* ip, const BYTE* const iLimit, const BYTE** matchpos, const int maxNbAttempts) @@ -161,7 +141,6 @@ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, /* I const U32 dictLimit = hc4->dictLimit; const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1); U32 matchIndex; - const BYTE* match; int nbAttempts=maxNbAttempts; size_t ml=0; @@ -169,24 +148,19 @@ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, /* I LZ4HC_Insert(hc4, ip); matchIndex = HashTable[LZ4HC_hashPtr(ip)]; - while ((matchIndex>=lowLimit) && (nbAttempts)) - { + while ((matchIndex>=lowLimit) && (nbAttempts)) { nbAttempts--; - if (matchIndex >= dictLimit) - { - match = base + matchIndex; + if (matchIndex >= dictLimit) { + const BYTE* const match = base + matchIndex; if (*(match+ml) == *(ip+ml) && (LZ4_read32(match) == LZ4_read32(ip))) { - size_t mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH; + size_t const mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH; if (mlt > ml) { ml = mlt; *matchpos = match; } } - } - else - { - match = dictBase + matchIndex; - if (LZ4_read32(match) == LZ4_read32(ip)) - { + } else { + const BYTE* const match = dictBase + matchIndex; + if (LZ4_read32(match) == LZ4_read32(ip)) { size_t mlt; const BYTE* vLimit = ip + (dictLimit - matchIndex); if (vLimit > iLimit) vLimit = iLimit; @@ -204,7 +178,7 @@ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, /* I FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch ( - LZ4HC_Data_Structure* hc4, + LZ4HC_CCtx_internal* hc4, const BYTE* const ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit, @@ -229,38 +203,32 @@ FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch ( LZ4HC_Insert(hc4, ip); matchIndex = HashTable[LZ4HC_hashPtr(ip)]; - while ((matchIndex>=lowLimit) && (nbAttempts)) - { + while ((matchIndex>=lowLimit) && (nbAttempts)) { nbAttempts--; - if (matchIndex >= dictLimit) - { + if (matchIndex >= dictLimit) { const BYTE* matchPtr = base + matchIndex; - if (*(iLowLimit + longest) == *(matchPtr - delta + longest)) - if (LZ4_read32(matchPtr) == LZ4_read32(ip)) - { + if (*(iLowLimit + longest) == *(matchPtr - delta + longest)) { + if (LZ4_read32(matchPtr) == LZ4_read32(ip)) { int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit); int back = 0; - while ((ip+back>iLowLimit) + while ((ip+back > iLowLimit) && (matchPtr+back > lowPrefixPtr) && (ip[back-1] == matchPtr[back-1])) back--; mlt -= back; - if (mlt > longest) - { + if (mlt > longest) { longest = (int)mlt; *matchpos = matchPtr+back; *startpos = ip+back; } } - } - else - { - const BYTE* matchPtr = dictBase + matchIndex; - if (LZ4_read32(matchPtr) == LZ4_read32(ip)) - { + } + } else { + const BYTE* const matchPtr = dictBase + matchIndex; + if (LZ4_read32(matchPtr) == LZ4_read32(ip)) { size_t mlt; int back=0; const BYTE* vLimit = ip + (dictLimit - matchIndex); @@ -320,8 +288,15 @@ FORCE_INLINE int LZ4HC_encodeSequence ( /* Encode MatchLength */ length = (int)(matchLength-MINMATCH); if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */ - if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; } - else *token += (BYTE)(length); + if (length>=(int)ML_MASK) { + *token += ML_MASK; + length -= ML_MASK; + for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } + if (length > 254) { length-=255; *(*op)++ = 255; } + *(*op)++ = (BYTE)length; + } else { + *token += (BYTE)(length); + } /* Prepare next loop */ *ip += matchLength; @@ -330,18 +305,18 @@ FORCE_INLINE int LZ4HC_encodeSequence ( return 0; } +#include "lz4opt.h" -static int LZ4HC_compress_generic ( - void* ctxvoid, - const char* source, - char* dest, - int inputSize, - int maxOutputSize, - int compressionLevel, +static int LZ4HC_compress_hashChain ( + LZ4HC_CCtx_internal* const ctx, + const char* const source, + char* const dest, + int const inputSize, + int const maxOutputSize, + unsigned maxNbAttempts, limitedOutput_directive limit ) { - LZ4HC_Data_Structure* ctx = (LZ4HC_Data_Structure*) ctxvoid; const BYTE* ip = (const BYTE*) source; const BYTE* anchor = ip; const BYTE* const iend = ip + inputSize; @@ -351,28 +326,22 @@ static int LZ4HC_compress_generic ( BYTE* op = (BYTE*) dest; BYTE* const oend = op + maxOutputSize; - unsigned maxNbAttempts; int ml, ml2, ml3, ml0; - const BYTE* ref=NULL; - const BYTE* start2=NULL; - const BYTE* ref2=NULL; - const BYTE* start3=NULL; - const BYTE* ref3=NULL; + const BYTE* ref = NULL; + const BYTE* start2 = NULL; + const BYTE* ref2 = NULL; + const BYTE* start3 = NULL; + const BYTE* ref3 = NULL; const BYTE* start0; const BYTE* ref0; - /* init */ - if (compressionLevel > g_maxCompressionLevel) compressionLevel = g_maxCompressionLevel; - if (compressionLevel < 1) compressionLevel = LZ4HC_compressionLevel_default; - maxNbAttempts = 1 << (compressionLevel-1); ctx->end += inputSize; ip++; /* Main Loop */ - while (ip < mflimit) - { + while (ip < mflimit) { ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts); if (!ml) { ip++; continue; } @@ -383,19 +352,16 @@ static int LZ4HC_compress_generic ( _Search2: if (ip+ml < mflimit) - ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2, maxNbAttempts); + ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 0, matchlimit, ml, &ref2, &start2, maxNbAttempts); else ml2 = ml; - if (ml2 == ml) /* No better match */ - { + if (ml2 == ml) { /* No better match */ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0; continue; } - if (start0 < ip) - { - if (start2 < ip + ml0) /* empirical */ - { + if (start0 < ip) { + if (start2 < ip + ml0) { /* empirical */ ip = start0; ref = ref0; ml = ml0; @@ -403,8 +369,7 @@ static int LZ4HC_compress_generic ( } /* Here, start0==ip */ - if ((start2 - ip) < 3) /* First Match too small : removed */ - { + if ((start2 - ip) < 3) { /* First Match too small : removed */ ml = ml2; ip = start2; ref =ref2; @@ -417,15 +382,13 @@ static int LZ4HC_compress_generic ( * ml2 > ml1, and * ip1+3 <= ip2 (usually < ip1+ml1) */ - if ((start2 - ip) < OPTIMAL_ML) - { + if ((start2 - ip) < OPTIMAL_ML) { int correction; int new_ml = ml; if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML; if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH; correction = new_ml - (int)(start2 - ip); - if (correction > 0) - { + if (correction > 0) { start2 += correction; ref2 += correction; ml2 -= correction; @@ -437,8 +400,7 @@ static int LZ4HC_compress_generic ( ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts); else ml3 = ml2; - if (ml3 == ml2) /* No better match : 2 sequences to encode */ - { + if (ml3 == ml2) { /* No better match : 2 sequences to encode */ /* ip & ref are known; Now for ml */ if (start2 < ip+ml) ml = (int)(start2 - ip); /* Now, encode 2 sequences */ @@ -448,18 +410,14 @@ static int LZ4HC_compress_generic ( continue; } - if (start3 < ip+ml+3) /* Not enough space for match 2 : remove it */ - { - if (start3 >= (ip+ml)) /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */ - { - if (start2 < ip+ml) - { + if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */ + if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */ + if (start2 < ip+ml) { int correction = (int)(ip+ml - start2); start2 += correction; ref2 += correction; ml2 -= correction; - if (ml2 < MINMATCH) - { + if (ml2 < MINMATCH) { start2 = start3; ref2 = ref3; ml2 = ml3; @@ -487,23 +445,18 @@ static int LZ4HC_compress_generic ( * OK, now we have 3 ascending matches; let's write at least the first one * ip & ref are known; Now for ml */ - if (start2 < ip+ml) - { - if ((start2 - ip) < (int)ML_MASK) - { + if (start2 < ip+ml) { + if ((start2 - ip) < (int)ML_MASK) { int correction; if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; correction = ml - (int)(start2 - ip); - if (correction > 0) - { + if (correction > 0) { start2 += correction; ref2 += correction; ml2 -= correction; } - } - else - { + } else { ml = (int)(start2 - ip); } } @@ -521,8 +474,7 @@ static int LZ4HC_compress_generic ( } /* Encode Last Literals */ - { - int lastRun = (int)(iend - anchor); + { int lastRun = (int)(iend - anchor); if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */ if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } else *op++ = (BYTE)(lastRun<<ML_BITS); @@ -534,23 +486,64 @@ static int LZ4HC_compress_generic ( return (int) (((char*)op)-dest); } +static int LZ4HC_getSearchNum(int compressionLevel) +{ + switch (compressionLevel) { + default: return 0; /* unused */ + case 11: return 128; + case 12: return 1<<10; + } +} -int LZ4_sizeofStateHC(void) { return sizeof(LZ4HC_Data_Structure); } +static int LZ4HC_compress_generic ( + LZ4HC_CCtx_internal* const ctx, + const char* const source, + char* const dest, + int const inputSize, + int const maxOutputSize, + int compressionLevel, + limitedOutput_directive limit + ) +{ + if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT; + if (compressionLevel > 9) { + switch (compressionLevel) { + case 10: return LZ4HC_compress_hashChain(ctx, source, dest, inputSize, maxOutputSize, 1 << (16-1), limit); + case 11: ctx->searchNum = LZ4HC_getSearchNum(compressionLevel); return LZ4HC_compress_optimal(ctx, source, dest, inputSize, maxOutputSize, limit, 128, 0); + default: + case 12: ctx->searchNum = LZ4HC_getSearchNum(compressionLevel); return LZ4HC_compress_optimal(ctx, source, dest, inputSize, maxOutputSize, limit, LZ4_OPT_NUM, 1); + } + } + return LZ4HC_compress_hashChain(ctx, source, dest, inputSize, maxOutputSize, 1 << (compressionLevel-1), limit); +} + + +int LZ4_sizeofStateHC(void) { return sizeof(LZ4_streamHC_t); } int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel) { + LZ4HC_CCtx_internal* ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */ - LZ4HC_init ((LZ4HC_Data_Structure*)state, (const BYTE*)src); + LZ4HC_init (ctx, (const BYTE*)src); if (maxDstSize < LZ4_compressBound(srcSize)) - return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput); + return LZ4HC_compress_generic (ctx, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput); else - return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, noLimit); + return LZ4HC_compress_generic (ctx, src, dst, srcSize, maxDstSize, compressionLevel, noLimit); } int LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel) { - LZ4HC_Data_Structure state; - return LZ4_compress_HC_extStateHC(&state, src, dst, srcSize, maxDstSize, compressionLevel); +#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 + LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); +#else + LZ4_streamHC_t state; + LZ4_streamHC_t* const statePtr = &state; +#endif + int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, maxDstSize, compressionLevel); +#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 + free(statePtr); +#endif + return cSize; } @@ -566,32 +559,38 @@ int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_st /* initialization */ void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { - LZ4_STATIC_ASSERT(sizeof(LZ4HC_Data_Structure) <= sizeof(LZ4_streamHC_t)); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ - ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->base = NULL; - ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->compressionLevel = (unsigned)compressionLevel; + LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= sizeof(size_t) * LZ4_STREAMHCSIZE_SIZET); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ + LZ4_streamHCPtr->internal_donotuse.base = NULL; + LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned)compressionLevel; + LZ4_streamHCPtr->internal_donotuse.searchNum = LZ4HC_getSearchNum(compressionLevel); } int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize) { - LZ4HC_Data_Structure* ctxPtr = (LZ4HC_Data_Structure*) LZ4_streamHCPtr; - if (dictSize > 64 KB) - { + LZ4HC_CCtx_internal* ctxPtr = &LZ4_streamHCPtr->internal_donotuse; + if (dictSize > 64 KB) { dictionary += dictSize - 64 KB; dictSize = 64 KB; } LZ4HC_init (ctxPtr, (const BYTE*)dictionary); - if (dictSize >= 4) LZ4HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3)); ctxPtr->end = (const BYTE*)dictionary + dictSize; + if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN) + LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS); + else + if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); return dictSize; } /* compression */ -static void LZ4HC_setExternalDict(LZ4HC_Data_Structure* ctxPtr, const BYTE* newBlock) +static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock) { - if (ctxPtr->end >= ctxPtr->base + 4) - LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ + if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN) + LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS); + else + if (ctxPtr->end >= ctxPtr->base + 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ + /* Only one memory segment for extDict, so any previous extDict is lost at this stage */ ctxPtr->lowLimit = ctxPtr->dictLimit; ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base); @@ -601,34 +600,29 @@ static void LZ4HC_setExternalDict(LZ4HC_Data_Structure* ctxPtr, const BYTE* newB ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */ } -static int LZ4_compressHC_continue_generic (LZ4HC_Data_Structure* ctxPtr, +static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize, limitedOutput_directive limit) { + LZ4HC_CCtx_internal* ctxPtr = &LZ4_streamHCPtr->internal_donotuse; /* auto-init if forgotten */ - if (ctxPtr->base == NULL) - LZ4HC_init (ctxPtr, (const BYTE*) source); + if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const BYTE*) source); /* Check overflow */ - if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) - { + if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) { size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit; if (dictSize > 64 KB) dictSize = 64 KB; - - LZ4_loadDictHC((LZ4_streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize); + LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize); } /* Check if blocks follow each other */ - if ((const BYTE*)source != ctxPtr->end) - LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source); + if ((const BYTE*)source != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source); /* Check overlapping input/dictionary space */ - { - const BYTE* sourceEnd = (const BYTE*) source + inputSize; - const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit; - const BYTE* dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit; - if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) - { + { const BYTE* sourceEnd = (const BYTE*) source + inputSize; + const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit; + const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit; + if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) { if (sourceEnd > dictEnd) sourceEnd = dictEnd; ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase); if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit; @@ -641,9 +635,9 @@ static int LZ4_compressHC_continue_generic (LZ4HC_Data_Structure* ctxPtr, int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize) { if (maxOutputSize < LZ4_compressBound(inputSize)) - return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput); + return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput); else - return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit); + return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit); } @@ -651,14 +645,13 @@ int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* sourc int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize) { - LZ4HC_Data_Structure* streamPtr = (LZ4HC_Data_Structure*)LZ4_streamHCPtr; - int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit)); + LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse; + int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit)); if (dictSize > 64 KB) dictSize = 64 KB; if (dictSize < 4) dictSize = 0; if (dictSize > prefixSize) dictSize = prefixSize; memmove(safeBuffer, streamPtr->end - dictSize, dictSize); - { - U32 endIndex = (U32)(streamPtr->end - streamPtr->base); + { U32 const endIndex = (U32)(streamPtr->end - streamPtr->base); streamPtr->end = (const BYTE*)safeBuffer + dictSize; streamPtr->base = streamPtr->end - endIndex; streamPtr->dictLimit = endIndex - dictSize; @@ -672,8 +665,8 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS /*********************************** * Deprecated Functions ***********************************/ +/* These functions currently generate deprecation warnings */ /* Deprecated compression functions */ -/* These functions are planned to start generate warnings by r131 approximately */ int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); } int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); } int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } @@ -687,45 +680,41 @@ int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, /* Deprecated streaming functions */ -/* These functions currently generate deprecation warnings */ int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; } int LZ4_resetStreamStateHC(void* state, char* inputBuffer) { + LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */ - LZ4HC_init((LZ4HC_Data_Structure*)state, (const BYTE*)inputBuffer); - ((LZ4HC_Data_Structure*)state)->inputBuffer = (BYTE*)inputBuffer; + LZ4HC_init(ctx, (const BYTE*)inputBuffer); + ctx->inputBuffer = (BYTE*)inputBuffer; return 0; } void* LZ4_createHC (char* inputBuffer) { - void* hc4 = ALLOCATOR(1, sizeof(LZ4HC_Data_Structure)); + LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOCATOR(1, sizeof(LZ4_streamHC_t)); if (hc4 == NULL) return NULL; /* not enough memory */ - LZ4HC_init ((LZ4HC_Data_Structure*)hc4, (const BYTE*)inputBuffer); - ((LZ4HC_Data_Structure*)hc4)->inputBuffer = (BYTE*)inputBuffer; + LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer); + hc4->internal_donotuse.inputBuffer = (BYTE*)inputBuffer; return hc4; } -int LZ4_freeHC (void* LZ4HC_Data) -{ - FREEMEM(LZ4HC_Data); - return (0); -} +int LZ4_freeHC (void* LZ4HC_Data) { FREEMEM(LZ4HC_Data); return 0; } int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel) { - return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, 0, compressionLevel, noLimit); + return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, source, dest, inputSize, 0, compressionLevel, noLimit); } int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel) { - return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput); + return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput); } char* LZ4_slideInputBufferHC(void* LZ4HC_Data) { - LZ4HC_Data_Structure* hc4 = (LZ4HC_Data_Structure*)LZ4HC_Data; - int dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB); + LZ4HC_CCtx_internal* const hc4 = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse; + int const dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB); return (char*)(hc4->inputBuffer + dictSize); } diff --git a/Source/ThirdParty/LZ4/lz4hc.h b/Source/ThirdParty/LZ4/lz4hc.h index 431f7c87c8..1036fd0bf5 100644 --- a/Source/ThirdParty/LZ4/lz4hc.h +++ b/Source/ThirdParty/LZ4/lz4hc.h @@ -1,7 +1,7 @@ /* LZ4 HC - High Compression Mode of LZ4 Header File - Copyright (C) 2011-2015, Yann Collet. + Copyright (C) 2011-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without @@ -28,107 +28,92 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 + - LZ4 source repository : https://github.com/lz4/lz4 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c */ -#pragma once - +#ifndef LZ4_HC_H_19834876238432 +#define LZ4_HC_H_19834876238432 #if defined (__cplusplus) extern "C" { #endif -/***************************** -* Includes -*****************************/ -#include <stddef.h> /* size_t */ +/* --- Dependency --- */ +/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */ +#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */ -/************************************** -* Block Compression -**************************************/ -int LZ4_compress_HC (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel); -/* -LZ4_compress_HC : - Destination buffer 'dst' must be already allocated. - Compression completion is guaranteed if 'dst' buffer is sized to handle worst circumstances (data not compressible) - Worst size evaluation is provided by function LZ4_compressBound() (see "lz4.h") - srcSize : Max supported value is LZ4_MAX_INPUT_SIZE (see "lz4.h") - compressionLevel : Recommended values are between 4 and 9, although any value between 0 and 16 will work. - 0 means "use default value" (see lz4hc.c). - Values >16 behave the same as 16. - return : the number of bytes written into buffer 'dst' - or 0 if compression fails. -*/ - - -/* Note : - Decompression functions are provided within LZ4 source code (see "lz4.h") (BSD license) -*/ +/* --- Useful constants --- */ +#define LZ4HC_CLEVEL_MIN 3 +#define LZ4HC_CLEVEL_DEFAULT 9 +#define LZ4HC_CLEVEL_OPT_MIN 11 +#define LZ4HC_CLEVEL_MAX 12 -int LZ4_sizeofStateHC(void); -int LZ4_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel); -/* -LZ4_compress_HC_extStateHC() : - Use this function if you prefer to manually allocate memory for compression tables. - To know how much memory must be allocated for the compression tables, use : - int LZ4_sizeofStateHC(); +/*-************************************ + * Block Compression + **************************************/ +/*! LZ4_compress_HC() : + * Compress data from `src` into `dst`, using the more powerful but slower "HC" algorithm. + * `dst` must be already allocated. + * Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h") + * Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h") + * `compressionLevel` : Recommended values are between 4 and 9, although any value between 1 and LZ4HC_MAX_CLEVEL will work. + * Values >LZ4HC_MAX_CLEVEL behave the same as LZ4HC_MAX_CLEVEL. + * @return : the number of bytes written into 'dst' + * or 0 if compression fails. + */ +LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel); - Allocated memory must be aligned on 8-bytes boundaries (which a normal malloc() will do properly). - The allocated memory can then be provided to the compression functions using 'void* state' parameter. - LZ4_compress_HC_extStateHC() is equivalent to previously described function. - It just uses externally allocated memory for stateHC. -*/ +/* Note : + * Decompression functions are provided within "lz4.h" (BSD license) + */ -/************************************** -* Streaming Compression -**************************************/ -#define LZ4_STREAMHCSIZE 262192 -#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t)) -typedef struct { size_t table[LZ4_STREAMHCSIZE_SIZET]; } LZ4_streamHC_t; -/* - LZ4_streamHC_t - This structure allows static allocation of LZ4 HC streaming state. - State must then be initialized using LZ4_resetStreamHC() before first use. +/*! LZ4_compress_HC_extStateHC() : + * Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`. + * `state` size is provided by LZ4_sizeofStateHC(). + * Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() will do properly). + */ +LZ4LIB_API int LZ4_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel); +LZ4LIB_API int LZ4_sizeofStateHC(void); - Static allocation should only be used in combination with static linking. - If you want to use LZ4 as a DLL, please use construction functions below, which are future-proof. -*/ +/*-************************************ + * Streaming Compression + * Bufferless synchronous API + **************************************/ + typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */ -LZ4_streamHC_t* LZ4_createStreamHC(void); -int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); -/* - These functions create and release memory for LZ4 HC streaming state. - Newly created states are already initialized. - Existing state space can be re-used anytime using LZ4_resetStreamHC(). - If you use LZ4 as a DLL, use these functions instead of static structure allocation, - to avoid size mismatch between different versions. -*/ +/*! LZ4_createStreamHC() and LZ4_freeStreamHC() : + * These functions create and release memory for LZ4 HC streaming state. + * Newly created states are automatically initialized. + * Existing states can be re-used several times, using LZ4_resetStreamHC(). + * These methods are API and ABI stable, they can be used in combination with a DLL. + */ +LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void); +LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); -void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); -int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize); +LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); +LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize); -int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize); +LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize); -int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize); +LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize); /* These functions compress data in successive blocks of any size, using previous blocks as dictionary. One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks. - There is an exception for ring buffers, which can be smaller 64 KB. - Such case is automatically detected and correctly handled by LZ4_compress_HC_continue(). + There is an exception for ring buffers, which can be smaller than 64 KB. + Ring buffers scenario is automatically detected and handled by LZ4_compress_HC_continue(). Before starting compression, state must be properly initialized, using LZ4_resetStreamHC(). A first "fictional block" can then be designated as initial dictionary, using LZ4_loadDictHC() (Optional). Then, use LZ4_compress_HC_continue() to compress each successive block. - It works like LZ4_compress_HC(), but use previous memory blocks as dictionary to improve compression. Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression. - As a reminder, size 'dst' buffer to handle worst cases, using LZ4_compressBound(), to ensure success of compression operation. + 'dst' buffer should be sized to handle worst case scenarios, using LZ4_compressBound(), to ensure operation success. If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block, you must save it to a safer memory space, using LZ4_saveDictHC(). @@ -136,50 +121,102 @@ int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSi */ +/*-****************************************** + * !!!!! STATIC LINKING ONLY !!!!! + *******************************************/ + + /*-************************************* + * PRIVATE DEFINITIONS : + * Do not use these definitions. + * They are exposed to allow static allocation of `LZ4_streamHC_t`. + * Using these definitions makes the code vulnerable to potential API break when upgrading LZ4 + **************************************/ +#define LZ4HC_DICTIONARY_LOGSIZE 17 +#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE) +#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1) + +#define LZ4HC_HASH_LOG 15 +#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG) +#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1) + + +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#include <stdint.h> + +typedef struct +{ + uint32_t hashTable[LZ4HC_HASHTABLESIZE]; + uint16_t chainTable[LZ4HC_MAXD]; + const uint8_t* end; /* next block here to continue on current prefix */ + const uint8_t* base; /* All index relative to this position */ + const uint8_t* dictBase; /* alternate base for extDict */ + uint8_t* inputBuffer; /* deprecated */ + uint32_t dictLimit; /* below that point, need extDict */ + uint32_t lowLimit; /* below that point, no more dict */ + uint32_t nextToUpdate; /* index from which to continue dictionary update */ + uint32_t searchNum; /* only for optimal parser */ + uint32_t compressionLevel; +} LZ4HC_CCtx_internal; + +#else + +typedef struct +{ + unsigned int hashTable[LZ4HC_HASHTABLESIZE]; + unsigned short chainTable[LZ4HC_MAXD]; + const unsigned char* end; /* next block here to continue on current prefix */ + const unsigned char* base; /* All index relative to this position */ + const unsigned char* dictBase; /* alternate base for extDict */ + unsigned char* inputBuffer; /* deprecated */ + unsigned int dictLimit; /* below that point, need extDict */ + unsigned int lowLimit; /* below that point, no more dict */ + unsigned int nextToUpdate; /* index from which to continue dictionary update */ + unsigned int searchNum; /* only for optimal parser */ + unsigned int compressionLevel; +} LZ4HC_CCtx_internal; + +#endif + +#define LZ4_STREAMHCSIZE (4*LZ4HC_HASHTABLESIZE + 2*LZ4HC_MAXD + 56) /* 393268 */ +#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t)) +union LZ4_streamHC_u { + size_t table[LZ4_STREAMHCSIZE_SIZET]; + LZ4HC_CCtx_internal internal_donotuse; +}; /* previously typedef'd to LZ4_streamHC_t */ +/* + LZ4_streamHC_t : + This structure allows static allocation of LZ4 HC streaming state. + State must be initialized using LZ4_resetStreamHC() before first use. + + Static allocation shall only be used in combination with static linking. + When invoking LZ4 from a DLL, use create/free functions instead, which are API and ABI stable. +*/ + -/************************************** +/*-************************************ * Deprecated Functions **************************************/ -/* Deprecate Warnings */ -/* Should these warnings messages be a problem, - it is generally possible to disable them, - with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual for example. - You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */ -#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK -# define LZ4_DEPRECATE_WARNING_DEFBLOCK -# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -# if (LZ4_GCC_VERSION >= 405) || defined(__clang__) -# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) -# elif (LZ4_GCC_VERSION >= 301) -# define LZ4_DEPRECATED(message) __attribute__((deprecated)) -# elif defined(_MSC_VER) -# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) -# else -# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") -# define LZ4_DEPRECATED(message) -# endif -#endif // LZ4_DEPRECATE_WARNING_DEFBLOCK - -/* compression functions */ -/* these functions are planned to trigger warning messages by r131 approximately */ -int LZ4_compressHC (const char* source, char* dest, int inputSize); -int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize); -int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel); -int LZ4_compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); -int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize); -int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); -int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel); -int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); -int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize); -int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize); - -/* Streaming functions following the older model; should no longer be used */ +/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */ + +/* deprecated compression functions */ +/* these functions will trigger warning messages in future releases */ +LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC (const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize); + +/* Deprecated Streaming functions using older model; should no longer be used */ LZ4_DEPRECATED("use LZ4_createStreamHC() instead") void* LZ4_createHC (char* inputBuffer); LZ4_DEPRECATED("use LZ4_saveDictHC() instead") char* LZ4_slideInputBufferHC (void* LZ4HC_Data); LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") int LZ4_freeHC (void* LZ4HC_Data); -LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); -LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_createStreamHC() instead") int LZ4_sizeofStreamStateHC(void); LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") int LZ4_resetStreamStateHC(void* state, char* inputBuffer); @@ -187,3 +224,5 @@ LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") int LZ4_resetStreamStateHC( #if defined (__cplusplus) } #endif + +#endif /* LZ4_HC_H_19834876238432 */ diff --git a/Source/ThirdParty/LZ4/lz4opt.h b/Source/ThirdParty/LZ4/lz4opt.h new file mode 100644 index 0000000000..d1913fe1cb --- /dev/null +++ b/Source/ThirdParty/LZ4/lz4opt.h @@ -0,0 +1,363 @@ +/* + lz4opt.h - Optimal Mode of LZ4 + Copyright (C) 2015-2016, Przemyslaw Skibinski <inikep@gmail.com> + Note : this file is intended to be included within lz4hc.c + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + 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 + OWNER 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. + + You can contact the author at : + - LZ4 source repository : https://github.com/lz4/lz4 + - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c +*/ + +#define LZ4_OPT_NUM (1<<12) + + +typedef struct +{ + int off; + int len; +} LZ4HC_match_t; + +typedef struct +{ + int price; + int off; + int mlen; + int litlen; +} LZ4HC_optimal_t; + + +/* price in bits */ +FORCE_INLINE size_t LZ4HC_literalsPrice(size_t litlen) +{ + size_t price = 8*litlen; + if (litlen >= (size_t)RUN_MASK) price+=8*(1+(litlen-RUN_MASK)/255); + return price; +} + + +/* requires mlen >= MINMATCH */ +FORCE_INLINE size_t LZ4HC_sequencePrice(size_t litlen, size_t mlen) +{ + size_t price = 16 + 8; /* 16-bit offset + token */ + + price += LZ4HC_literalsPrice(litlen); + + mlen -= MINMATCH; + if (mlen >= (size_t)ML_MASK) price+=8*(1+(mlen-ML_MASK)/255); + + return price; +} + + +/*-************************************* +* Binary Tree search +***************************************/ +FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches ( + LZ4HC_CCtx_internal* ctx, + const BYTE* const ip, + const BYTE* const iHighLimit, + size_t best_mlen, + LZ4HC_match_t* matches, + int* matchNum) +{ + U16* const chainTable = ctx->chainTable; + U32* const HashTable = ctx->hashTable; + const BYTE* const base = ctx->base; + const U32 dictLimit = ctx->dictLimit; + const U32 current = (U32)(ip - base); + const U32 lowLimit = (ctx->lowLimit + MAX_DISTANCE > current) ? ctx->lowLimit : current - (MAX_DISTANCE - 1); + const BYTE* const dictBase = ctx->dictBase; + const BYTE* match; + int nbAttempts = ctx->searchNum; + int mnum = 0; + U16 *ptr0, *ptr1, delta0, delta1; + U32 matchIndex; + size_t matchLength = 0; + U32* HashPos; + + if (ip + MINMATCH > iHighLimit) return 1; + + /* HC4 match finder */ + HashPos = &HashTable[LZ4HC_hashPtr(ip)]; + matchIndex = *HashPos; + *HashPos = current; + + ptr0 = &DELTANEXTMAXD(current*2+1); + ptr1 = &DELTANEXTMAXD(current*2); + delta0 = delta1 = (U16)(current - matchIndex); + + while ((matchIndex < current) && (matchIndex>=lowLimit) && (nbAttempts)) { + nbAttempts--; + if (matchIndex >= dictLimit) { + match = base + matchIndex; + matchLength = LZ4_count(ip, match, iHighLimit); + } else { + const BYTE* vLimit = ip + (dictLimit - matchIndex); + match = dictBase + matchIndex; + if (vLimit > iHighLimit) vLimit = iHighLimit; + matchLength = LZ4_count(ip, match, vLimit); + if ((ip+matchLength == vLimit) && (vLimit < iHighLimit)) + matchLength += LZ4_count(ip+matchLength, base+dictLimit, iHighLimit); + } + + if (matchLength > best_mlen) { + best_mlen = matchLength; + if (matches) { + if (matchIndex >= dictLimit) + matches[mnum].off = (int)(ip - match); + else + matches[mnum].off = (int)(ip - (base + matchIndex)); /* virtual matchpos */ + matches[mnum].len = (int)matchLength; + mnum++; + } + if (best_mlen > LZ4_OPT_NUM) break; + } + + if (ip+matchLength >= iHighLimit) /* equal : no way to know if inf or sup */ + break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */ + + if (*(ip+matchLength) < *(match+matchLength)) { + *ptr0 = delta0; + ptr0 = &DELTANEXTMAXD(matchIndex*2); + if (*ptr0 == (U16)-1) break; + delta0 = *ptr0; + delta1 += delta0; + matchIndex -= delta0; + } else { + *ptr1 = delta1; + ptr1 = &DELTANEXTMAXD(matchIndex*2+1); + if (*ptr1 == (U16)-1) break; + delta1 = *ptr1; + delta0 += delta1; + matchIndex -= delta1; + } + } + + *ptr0 = (U16)-1; + *ptr1 = (U16)-1; + if (matchNum) *matchNum = mnum; + /* if (best_mlen > 8) return best_mlen-8; */ + if (!matchNum) return 1; + return 1; +} + + +FORCE_INLINE void LZ4HC_updateBinTree(LZ4HC_CCtx_internal* ctx, const BYTE* const ip, const BYTE* const iHighLimit) +{ + const BYTE* const base = ctx->base; + const U32 target = (U32)(ip - base); + U32 idx = ctx->nextToUpdate; + while(idx < target) + idx += LZ4HC_BinTree_InsertAndGetAllMatches(ctx, base+idx, iHighLimit, 8, NULL, NULL); +} + + +/** Tree updater, providing best match */ +FORCE_INLINE int LZ4HC_BinTree_GetAllMatches ( + LZ4HC_CCtx_internal* ctx, + const BYTE* const ip, const BYTE* const iHighLimit, + size_t best_mlen, LZ4HC_match_t* matches, const int fullUpdate) +{ + int mnum = 0; + if (ip < ctx->base + ctx->nextToUpdate) return 0; /* skipped area */ + if (fullUpdate) LZ4HC_updateBinTree(ctx, ip, iHighLimit); + best_mlen = LZ4HC_BinTree_InsertAndGetAllMatches(ctx, ip, iHighLimit, best_mlen, matches, &mnum); + ctx->nextToUpdate = (U32)(ip - ctx->base + best_mlen); + return mnum; +} + + +#define SET_PRICE(pos, mlen, offset, litlen, price) \ +{ \ + while (last_pos < pos) { opt[last_pos+1].price = 1<<30; last_pos++; } \ + opt[pos].mlen = (int)mlen; \ + opt[pos].off = (int)offset; \ + opt[pos].litlen = (int)litlen; \ + opt[pos].price = (int)price; \ +} + + +static int LZ4HC_compress_optimal ( + LZ4HC_CCtx_internal* ctx, + const char* const source, + char* dest, + int inputSize, + int maxOutputSize, + limitedOutput_directive limit, + const size_t sufficient_len, + const int fullUpdate + ) +{ + LZ4HC_optimal_t opt[LZ4_OPT_NUM + 1]; + LZ4HC_match_t matches[LZ4_OPT_NUM + 1]; + const BYTE *inr = NULL; + size_t res, cur, cur2; + size_t i, llen, litlen, mlen, best_mlen, price, offset, best_off, match_num, last_pos; + + const BYTE* ip = (const BYTE*) source; + const BYTE* anchor = ip; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = (iend - LASTLITERALS); + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + maxOutputSize; + + /* init */ + ctx->end += inputSize; + ip++; + + /* Main Loop */ + while (ip < mflimit) { + memset(opt, 0, sizeof(LZ4HC_optimal_t)); + last_pos = 0; + llen = ip - anchor; + match_num = LZ4HC_BinTree_GetAllMatches(ctx, ip, matchlimit, MINMATCH-1, matches, fullUpdate); + if (!match_num) { ip++; continue; } + + if ((size_t)matches[match_num-1].len > sufficient_len) { + best_mlen = matches[match_num-1].len; + best_off = matches[match_num-1].off; + cur = 0; + last_pos = 1; + goto encode; + } + + /* set prices using matches at position = 0 */ + for (i = 0; i < match_num; i++) { + mlen = (i>0) ? (size_t)matches[i-1].len+1 : MINMATCH; + best_mlen = (matches[i].len < LZ4_OPT_NUM) ? matches[i].len : LZ4_OPT_NUM; + while (mlen <= best_mlen) { + litlen = 0; + price = LZ4HC_sequencePrice(llen + litlen, mlen) - LZ4HC_literalsPrice(llen); + SET_PRICE(mlen, mlen, matches[i].off, litlen, price); + mlen++; + } + } + + if (last_pos < MINMATCH) { ip++; continue; } + + /* check further positions */ + opt[0].mlen = opt[1].mlen = 1; + for (cur = 1; cur <= last_pos; cur++) { + inr = ip + cur; + + if (opt[cur-1].mlen == 1) { + litlen = opt[cur-1].litlen + 1; + if (cur != litlen) { + price = opt[cur - litlen].price + LZ4HC_literalsPrice(litlen); + } else { + price = LZ4HC_literalsPrice(llen + litlen) - LZ4HC_literalsPrice(llen); + } + } else { + litlen = 1; + price = opt[cur - 1].price + LZ4HC_literalsPrice(litlen); + } + + mlen = 1; + best_mlen = 0; + if (cur > last_pos || price < (size_t)opt[cur].price) + SET_PRICE(cur, mlen, best_mlen, litlen, price); + + if (cur == last_pos || inr >= mflimit) break; + + match_num = LZ4HC_BinTree_GetAllMatches(ctx, inr, matchlimit, MINMATCH-1, matches, fullUpdate); + if (match_num > 0 && (size_t)matches[match_num-1].len > sufficient_len) { + best_mlen = matches[match_num-1].len; + best_off = matches[match_num-1].off; + last_pos = cur + 1; + goto encode; + } + + /* set prices using matches at position = cur */ + for (i = 0; i < match_num; i++) { + mlen = (i>0) ? (size_t)matches[i-1].len+1 : MINMATCH; + cur2 = cur; + best_mlen = (cur2 + matches[i].len < LZ4_OPT_NUM) ? (size_t)matches[i].len : LZ4_OPT_NUM - cur2; + + while (mlen <= best_mlen) { + if (opt[cur2].mlen == 1) { + litlen = opt[cur2].litlen; + + if (cur2 != litlen) + price = opt[cur2 - litlen].price + LZ4HC_sequencePrice(litlen, mlen); + else + price = LZ4HC_sequencePrice(llen + litlen, mlen) - LZ4HC_literalsPrice(llen); + } else { + litlen = 0; + price = opt[cur2].price + LZ4HC_sequencePrice(litlen, mlen); + } + + if (cur2 + mlen > last_pos || price < (size_t)opt[cur2 + mlen].price) { // || (((int)price == opt[cur2 + mlen].price) && (opt[cur2 + mlen-1].mlen == 1))) { + SET_PRICE(cur2 + mlen, mlen, matches[i].off, litlen, price); + } + mlen++; + } + } + } /* for (cur = 1; cur <= last_pos; cur++) */ + + best_mlen = opt[last_pos].mlen; + best_off = opt[last_pos].off; + cur = last_pos - best_mlen; + +encode: /* cur, last_pos, best_mlen, best_off have to be set */ + opt[0].mlen = 1; + while (1) { + mlen = opt[cur].mlen; + offset = opt[cur].off; + opt[cur].mlen = (int)best_mlen; + opt[cur].off = (int)best_off; + best_mlen = mlen; + best_off = offset; + if (mlen > cur) break; + cur -= mlen; + } + + cur = 0; + while (cur < last_pos) { + mlen = opt[cur].mlen; + if (mlen == 1) { ip++; cur++; continue; } + offset = opt[cur].off; + cur += mlen; + + res = LZ4HC_encodeSequence(&ip, &op, &anchor, (int)mlen, ip - offset, limit, oend); + if (res) return 0; + } + } + + /* Encode Last Literals */ + { int lastRun = (int)(iend - anchor); + if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */ + if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } + else *op++ = (BYTE)(lastRun<<ML_BITS); + memcpy(op, anchor, iend - anchor); + op += iend-anchor; + } + + /* End */ + return (int) ((char*)op-dest); +} diff --git a/Source/ThirdParty/SDL/CMakeLists.txt b/Source/ThirdParty/SDL/CMakeLists.txt index aa81d49932..39b92359f0 100644 --- a/Source/ThirdParty/SDL/CMakeLists.txt +++ b/Source/ThirdParty/SDL/CMakeLists.txt @@ -177,7 +177,7 @@ set (SDL_CFLAGS) # in this file need to change that, so remember the original value, and # restore back to that afterwards. For check_function_exists() to work in # Emscripten, this value must be at its default value. -# Urho3D - also due to a CMake's try_compile() bug on iOS platform, the CMAKE_REQUIRED_FLAGS contains our SmileyHack-injection on iOS platform +# Urho3D - also due to a CMake's try_compile() bug on iOS/tvOS platform, the CMAKE_REQUIRED_FLAGS contains our SmileyHack-injection on iOS/tvOS platform set (ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) # Urho3D - save the original CMake global settings, do not leave them to chances set (ORIG_CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES}) @@ -276,7 +276,7 @@ dep_option(VIDEO_OPENGLES "Include OpenGL ES support" ON "NOT MINGW" OFF) dep_option(PTHREADS "Use POSIX threads for multi-threading" ON UNIX OFF) dep_option(PTHREADS_SEM "Use pthread semaphores" ON PTHREADS OFF) # Urho3D - SDL_DLOPEN was originally set as option twice (one here and one in the subsystem section above), we keep the one here so that we can make the option dependent on other conditions -dep_option(SDL_DLOPEN "Use dlopen for shared object loading" ON "UNIX\;NOT IOS OR NOT IPHONEOS_DEPLOYMENT_TARGET OR NOT IPHONEOS_DEPLOYMENT_TARGET VERSION_LESS 8" OFF) +dep_option(SDL_DLOPEN "Use dlopen for shared object loading" ON "UNIX\;NOT IOS OR NOT IPHONEOS_DEPLOYMENT_TARGET OR NOT IPHONEOS_DEPLOYMENT_TARGET VERSION_LESS 8" OFF) # No need to check for tvOS as its target version is 9 or above # Urho3D - hide Unix-specific audio driver options from Android platform dep_option(OSS "Support the OSS audio API" ON UNIX_SYS OFF) dep_option(ALSA "Support the ALSA audio API" ON UNIX_SYS OFF) @@ -292,7 +292,7 @@ dep_option(NAS_SHARED "Dynamically load NAS audio API" ON NAS OFF) dep_option(SNDIO "Support the Roar audio API" ON UNIX_SYS OFF) # Urho3D - commented out RPATH as an option because Urho3D is configured to always use RPATH, so init the variable to always TRUE set (RPATH TRUE) -# Urho3D - prefer clock_gettime() when it is available (hide the option for Windows) +# Urho3D - prefer clock_gettime() when it is available dep_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" ON "NOT WINDOWS" OFF) set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS}) dep_option(VIDEO_WAYLAND "Use Wayland video driver" ON UNIX_SYS OFF) @@ -466,7 +466,7 @@ if(ASSEMBLY) endif() # Urho3D - move from Unix platform-specific section below to here -if(CLOCK_GETTIME) +if(CLOCK_GETTIME AND (NOT IOS OR IPHONEOS_DEPLOYMENT_TARGET STREQUAL "" OR NOT IPHONEOS_DEPLOYMENT_TARGET VERSION_LESS 10.0)) # We cheat a little bit here with a hard-coded check because iOS 10.3 SDK when targeting 9.3 has strong symbol for iPhoneOS archs but weak symbol for iPhoneSimulator archs # Urho3D - bug fix - use different variables for different checks because of CMake caches the result variable; this fix the detection on Android platform check_library_exists(rt clock_gettime "" FOUND_CLOCK_GETTIME_IN_RT) if(FOUND_CLOCK_GETTIME_IN_RT) @@ -521,7 +521,7 @@ if(LIBC) set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_SYS_TYPES_SAVED}) # Urho3D - no fix required - it seems all the compiler toolchains (native and X-compiling) that have been tested are able to find these headers correctly # Android NDK is able to find these headers with the help of "--sysroot" compiler flags, while others like MinGW and Linaro GCC for RPI work out of box - # However, AppleClang when targeting iOS platform can only find these headers correctly AFTER applying a CMake hack from our common module to workaround a CMake bug so that try_compile() command works well on iOS platform + # However, AppleClang when targeting iOS/tvOS platform can only find these headers correctly AFTER applying a CMake hack from our common module to workaround a CMake bug so that try_compile() command works well on iOS/tvOS platform foreach(_HEADER stdio.h stdlib.h stddef.h stdarg.h malloc.h memory.h string.h strings.h inttypes.h stdint.h ctype.h math.h iconv.h signal.h) @@ -742,8 +742,8 @@ elseif(APPLE) endif() if(SDL_JOYSTICK) - # Urho3D - bug fix - make it work for iOS platform - if (IOS) + # Urho3D - bug fix - make it work for iOS/tvOS platform + if (IOS OR TVOS) set (SDL_JOYSTICK_MFI 1) file (GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m) else () @@ -758,8 +758,8 @@ elseif(APPLE) endif() if(SDL_HAPTIC) - # Urho3d - bug fix - make it work for iOS platform - if (IOS) + # Urho3d - bug fix - make it work for iOS/tvOS platform + if (IOS OR TVOS) set (SDL_HAPTIC_DUMMY 1) file (GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/dummy/*.c) else () @@ -776,8 +776,8 @@ elseif(APPLE) endif() if(SDL_POWER) - # Urho3d - bug fix - make it work for iOS platform - if (IOS) + # Urho3d - bug fix - make it work for iOS/tvOS platform + if (IOS OR TVOS) set (SDL_POWER_UIKIT 1) file (GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m) else () @@ -830,7 +830,7 @@ elseif(APPLE) list(APPEND EXTRA_LIBS ${AUDIOTOOLBOX}) endif() - # Urho3d - bug fix - make it work for iOS platform + # Urho3d - bug fix - make it work for iOS/tvOS platform if(SDL_VIDEO) if (VIDEO_COCOA) # Urho3D - these are moved from commented CheckCOCOA macro @@ -1118,6 +1118,14 @@ elseif(WINDOWS) if(DIRECTX) # Urho3D - bug fix - use our own FindDirectX.cmake module which does not rely on DXSDK_DIR environment variable directly when DirectX SDK is being used # Urho3D - TODO - move the find_package(DirectX) call from Urho3D common module to here later after we have refactored the library dependency handling + + check_struct_has_member (XINPUT_GAMEPAD_EX wButtons xinput.h HAVE_XINPUT_GAMEPAD_EX) + check_struct_has_member (XINPUT_STATE_EX dwPacketNumber xinput.h HAVE_XINPUT_STATE_EX) + foreach (VAR HAVE_XINPUT_GAMEPAD_EX HAVE_XINPUT_STATE_EX) + if (${VAR}) + add_definitions (-D${VAR}) + endif () + endforeach () endif() if(SDL_AUDIO) @@ -1426,6 +1434,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") # Define target name set (TARGET_NAME SDL) +# Define source files +file (GLOB H_FILES include/*.h) # Adding the headers into source files list is just for easier file browsing in the IDE +list (APPEND SOURCE_FILES ${H_FILES}) + # Setup target as STATIC library (as the result we never use EXTRA_LDFLAGS linker flags) setup_library () diff --git a/Source/ThirdParty/SDL/cmake/sdlchecks.cmake b/Source/ThirdParty/SDL/cmake/sdlchecks.cmake index e6e46c47e9..3c0a521249 100644 --- a/Source/ThirdParty/SDL/cmake/sdlchecks.cmake +++ b/Source/ThirdParty/SDL/cmake/sdlchecks.cmake @@ -794,7 +794,7 @@ endmacro() # Requires: # - nada -# Urho3D - rename the macro to be generic OpenGLES check and make it also work for iOS platform +# Urho3D - rename the macro to be generic OpenGLES check and make it also work for iOS/tvOS platform macro(CheckOpenGLES) if(VIDEO_OPENGLES) check_c_source_compiles(" diff --git a/Source/ThirdParty/SDL/include/SDL_config.h.cmake b/Source/ThirdParty/SDL/include/SDL_config.h.cmake index 8e28de62ef..8b6d0fe3ba 100644 --- a/Source/ThirdParty/SDL/include/SDL_config.h.cmake +++ b/Source/ThirdParty/SDL/include/SDL_config.h.cmake @@ -277,7 +277,7 @@ #cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@ #cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@ #cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@ -// Urho3D - needed on iOS platform +// Urho3D - needed on iOS/tvOS platform #cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@ #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@ #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@ @@ -344,7 +344,7 @@ #cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@ #cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@ #cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@ -// Urho3D - needed on iOS platform +// Urho3D - needed on iOS/tvOS platform #cmakedefine SDL_POWER_UIKIT @SDL_POWER_UIKIT@ #cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@ #cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@ @@ -372,7 +372,7 @@ /* Enable dynamic libsamplerate support */ #cmakedefine SDL_LIBSAMPLERATE_DYNAMIC @SDL_LIBSAMPLERATE_DYNAMIC@ -// Urho3D - needed on iOS platform +// Urho3D - needed on iOS/tvOS platform #cmakedefine SDL_IPHONE_KEYBOARD @SDL_IPHONE_KEYBOARD@ #cmakedefine SDL_IPHONE_LAUNCHSCREEN @SDL_IPHONE_LAUNCHSCREEN@ #cmakedefine SDL_IPHONE_MAX_GFORCE @SDL_IPHONE_MAX_GFORCE@ diff --git a/Source/ThirdParty/SDL/src/core/windows/SDL_xinput.h b/Source/ThirdParty/SDL/src/core/windows/SDL_xinput.h index 67f8fdc1f8..f8d7934d76 100644 --- a/Source/ThirdParty/SDL/src/core/windows/SDL_xinput.h +++ b/Source/ThirdParty/SDL/src/core/windows/SDL_xinput.h @@ -18,6 +18,9 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + +// Modified by Yao Wei Tjong for Urho3D + #include "../../SDL_internal.h" #ifndef _SDL_xinput_h @@ -100,6 +103,8 @@ #endif /* typedef's for XInput structs we use */ +// Urho3D - declara only when built-in xinput.h hasn't declared it +#ifndef HAVE_XINPUT_GAMEPAD_EX typedef struct { WORD wButtons; @@ -111,12 +116,14 @@ typedef struct SHORT sThumbRY; DWORD dwPaddingReserved; } XINPUT_GAMEPAD_EX; - +#endif +#ifndef HAVE_XINPUT_STATE_EX typedef struct { DWORD dwPacketNumber; XINPUT_GAMEPAD_EX Gamepad; } XINPUT_STATE_EX; +#endif typedef struct { diff --git a/Source/ThirdParty/SDL/src/video/uikit/SDL_uikitappdelegate.m b/Source/ThirdParty/SDL/src/video/uikit/SDL_uikitappdelegate.m index a9169c9e8c..4822c3cec7 100644 --- a/Source/ThirdParty/SDL/src/video/uikit/SDL_uikitappdelegate.m +++ b/Source/ThirdParty/SDL/src/video/uikit/SDL_uikitappdelegate.m @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -// Modified by Lasse Oorni for Urho3D +// Modified by Lasse Oorni and Yao Wei Tjong for Urho3D #include "../../SDL_internal.h" @@ -113,6 +113,14 @@ void SDL_IOS_LogMessage(const char *message) return documents_dir; } +// Urho3D: added function +#if TARGET_OS_TV +unsigned SDL_TVOS_GetActiveProcessorCount() +{ + return [NSProcessInfo class] ? (unsigned)[[NSProcessInfo processInfo] activeProcessorCount] : 1; +} +#endif + static void SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { diff --git a/Source/ThirdParty/SQLite/CMakeLists.txt b/Source/ThirdParty/SQLite/CMakeLists.txt index b86e7548d3..26428a2944 100644 --- a/Source/ThirdParty/SQLite/CMakeLists.txt +++ b/Source/ThirdParty/SQLite/CMakeLists.txt @@ -51,7 +51,7 @@ endforeach () # ATOMIC END # Setup additional SQLite CLI standalone target (this target can be transfered and executed on an embedded device, such as Raspberry Pi and Android) -if (NOT IOS AND NOT WEB AND NOT ANDROID) # ATOMIC FIX +if (NOT IOS AND NOT TVOS AND NOT WEB) # Define target name for SQLite shell set (TARGET_NAME isql) @@ -72,8 +72,8 @@ if (NOT IOS AND NOT WEB AND NOT ANDROID) # ATOMIC FIX setup_executable (NODEPS) endif () -# SQLite will not work correctly with the -ffast-math option of GCC +# SQLite will not work correctly with the -ffast-math option, so unset it in this scope only # ATOMIC: Add check for empty CMAKE_C_FLAGS if (CMAKE_C_FLAGS) - string (REPLACE -ffast-math "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) + string (REPLACE -ffast-math "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") # Stringify for string replacement endif() diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/allocators.h b/Source/ThirdParty/rapidjson/include/rapidjson/allocators.h index 969a1a3cdb..655f4a3854 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/allocators.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/allocators.h @@ -1,39 +1,53 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_ALLOCATORS_H_ #define RAPIDJSON_ALLOCATORS_H_ #include "rapidjson.h" -namespace rapidjson { +RAPIDJSON_NAMESPACE_BEGIN /////////////////////////////////////////////////////////////////////////////// // Allocator /*! \class rapidjson::Allocator - \brief Concept for allocating, resizing and freeing memory block. - - Note that Malloc() and Realloc() are non-static but Free() is static. - - So if an allocator need to support Free(), it needs to put its pointer in - the header of memory block. + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. \code concept Allocator { - static const bool kNeedFree; //!< Whether this allocator needs to call Free(). - - // Allocate a memory block. - // \param size of the memory block in bytes. - // \returns pointer to the memory block. - void* Malloc(size_t size); - - // Resize a memory block. - // \param originalPtr The pointer to current memory block. Null pointer is permitted. - // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) - // \param newSize the new size in bytes. - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); - - // Free a memory block. - // \param pointer to the memory block. Null pointer is permitted. - static void Free(void *ptr); + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); }; \endcode */ @@ -43,14 +57,26 @@ concept Allocator { //! C-runtime library allocator. /*! This class is just wrapper for standard C library memory routines. - \implements Allocator + \note implements Allocator concept */ class CrtAllocator { public: - static const bool kNeedFree = true; - void* Malloc(size_t size) { return malloc(size); } - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return realloc(originalPtr, newSize); } - static void Free(void *ptr) { free(ptr); } + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return std::malloc(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + std::free(originalPtr); + return NULL; + } + return std::realloc(originalPtr, newSize); + } + static void Free(void *ptr) { std::free(ptr); } }; /////////////////////////////////////////////////////////////////////////////// @@ -70,152 +96,176 @@ class CrtAllocator { The user-buffer is not deallocated by this allocator. \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. - \implements Allocator + \note implements Allocator concept */ template <typename BaseAllocator = CrtAllocator> class MemoryPoolAllocator { public: - static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) - - //! Constructor with chunkSize. - /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. - \param baseAllocator The allocator for allocating memory chunks. - */ - MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : - chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) - { - if (!baseAllocator_) - ownBaseAllocator_ = baseAllocator_ = new BaseAllocator(); - AddChunk(chunk_capacity_); - } - - //! Constructor with user-supplied buffer. - /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. - - The user buffer will not be deallocated when this allocator is destructed. - - \param buffer User supplied buffer. - \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). - \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. - \param baseAllocator The allocator for allocating memory chunks. - */ - MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : - chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) - { - RAPIDJSON_ASSERT(buffer != 0); - RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); - chunkHead_ = (ChunkHeader*)buffer; - chunkHead_->capacity = size - sizeof(ChunkHeader); - chunkHead_->size = 0; - chunkHead_->next = 0; - } - - //! Destructor. - /*! This deallocates all memory chunks, excluding the user-supplied buffer. - */ - ~MemoryPoolAllocator() { - Clear(); - delete ownBaseAllocator_; - } - - //! Deallocates all memory chunks, excluding the user-supplied buffer. - void Clear() { - while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) { - ChunkHeader* next = chunkHead_->next; - baseAllocator_->Free(chunkHead_); - chunkHead_ = next; - } - } - - //! Computes the total capacity of allocated memory chunks. - /*! \return total capacity in bytes. - */ - size_t Capacity() { - size_t capacity = 0; - for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) - capacity += c->capacity; - return capacity; - } - - //! Computes the memory blocks allocated. - /*! \return total used bytes. - */ - size_t Size() { - size_t size = 0; - for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) - size += c->size; - return size; - } - - //! Allocates a memory block. (concept Allocator) - void* Malloc(size_t size) { - size = RAPIDJSON_ALIGN(size); - if (chunkHead_->size + size > chunkHead_->capacity) - AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); - - char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size; - chunkHead_->size += size; - return buffer; - } - - //! Resizes a memory block (concept Allocator) - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { - if (originalPtr == 0) - return Malloc(newSize); - - // Do not shrink if new size is smaller than original - if (originalSize >= newSize) - return originalPtr; - - // Simply expand it if it is the last allocation and there is sufficient space - if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { - size_t increment = newSize - originalSize; - increment = RAPIDJSON_ALIGN(increment); - if (chunkHead_->size + increment <= chunkHead_->capacity) { - chunkHead_->size += increment; - return originalPtr; - } - } - - // Realloc process: allocate and copy memory, do not free original buffer. - void* newBuffer = Malloc(newSize); - RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. - return memcpy(newBuffer, originalPtr, originalSize); - } - - //! Frees a memory block (concept Allocator) - static void Free(void *ptr) { (void)ptr; } // Do nothing + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer); + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + RAPIDJSON_DELETE(ownBaseAllocator_); + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while (chunkHead_ && chunkHead_ != userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + if (chunkHead_ && chunkHead_ == userBuffer_) + chunkHead_->size = 0; // Clear user buffer + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + + void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + if (newSize == 0) + return NULL; + + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { + size_t increment = static_cast<size_t>(newSize - originalSize); + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) { (void)ptr; } // Do nothing private: - //! Creates a new chunk. - /*! \param capacity Capacity of the chunk in bytes. - */ - void AddChunk(size_t capacity) { - ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity); - chunk->capacity = capacity; - chunk->size = 0; - chunk->next = chunkHead_; - chunkHead_ = chunk; - } - - static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. - - //! Chunk header for perpending to each chunk. - /*! Chunks are stored as a singly linked list. - */ - struct ChunkHeader { - size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). - size_t size; //!< Current size of allocated memory in bytes. - ChunkHeader *next; //!< Next chunk in the linked list. - }; - - ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. - size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. - char *userBuffer_; //!< User supplied buffer. - BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. - BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. + //! Copy constructor is not permitted. + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; + //! Copy assignment operator is not permitted. + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; + + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); + if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + return true; + } + else + return false; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + void *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. }; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_ENCODINGS_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/document.h b/Source/ThirdParty/rapidjson/include/rapidjson/document.h index c68de6f786..c12820eeda 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/document.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/document.h @@ -1,692 +1,2062 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_DOCUMENT_H_ #define RAPIDJSON_DOCUMENT_H_ +/*! \file document.h */ + #include "reader.h" +#include "internal/meta.h" #include "internal/strfunc.h" -#include <new> // placement new +#include "memorystream.h" +#include "encodedstream.h" +#include <new> // placement new +#include <limits> +RAPIDJSON_DIAG_PUSH #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#ifdef _MINWINDEF_ // see: http://stackoverflow.com/questions/22744262/cant-call-stdmax-because-minwindef-h-defines-max +#ifndef NOMINMAX +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif +#endif +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#if __GNUC__ >= 6 +RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions +#endif +#endif // __GNUC__ + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include <iterator> // std::iterator, std::random_access_iterator_tag +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include <utility> // std::move +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template <typename Encoding, typename Allocator> +class GenericValue; + +template <typename Encoding, typename Allocator, typename StackAllocator> +class GenericDocument; + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template <typename Encoding, typename Allocator> +struct GenericMember { + GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) + GenericValue<Encoding, Allocator> value; //!< value of member. +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ <iterator> header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator + : public std::iterator<std::random_access_iterator_tag + , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> { + + friend class GenericValue<Encoding,Allocator>; + template <bool, typename, typename> friend class GenericMemberIterator; + + typedef GenericMember<Encoding,Allocator> PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } + bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } + bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } + bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } + bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } + bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template <bool Const, typename Encoding, typename Allocator> +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template <typename Encoding, typename Allocator> +struct GenericMemberIterator<false,Encoding,Allocator> { + //! use plain pointer as iterator type + typedef GenericMember<Encoding,Allocator>* Iterator; +}; +//! const GenericMemberIterator +template <typename Encoding, typename Allocator> +struct GenericMemberIterator<true,Encoding,Allocator> { + //! use plain const pointer as iterator type + typedef const GenericMember<Encoding,Allocator>* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template<typename CharType> +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + template<SizeType N> + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } + + //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ +#endif + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + //! Disallow construction from non-const array + template<SizeType N> + GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Copy assignment operator not permitted - immutable type + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; +}; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str) { + return GenericStringRef<CharType>(str, internal::StrLen(str)); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) { + return GenericStringRef<CharType>(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) { + return GenericStringRef<CharType>(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template <typename T, typename Encoding = void, typename Allocator = void> +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type> + : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template <typename ValueType, typename T> +struct TypeHelper {}; + +template<typename ValueType> +struct TypeHelper<ValueType, bool> { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, int> { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, unsigned> { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, int64_t> { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, uint64_t> { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, double> { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, float> { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, const typename ValueType::Ch*> { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template<typename ValueType> +struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { + typedef std::basic_string<typename ValueType::Ch> StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; #endif -namespace rapidjson { +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::Array> { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::ConstArray> { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::Object> { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::ConstObject> { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template <bool, typename> class GenericArray; +template <bool, typename> class GenericObject; /////////////////////////////////////////////////////////////////////////////// // GenericValue //! Represents a JSON value. Use Value for UTF8 encoding and default allocator. /*! - A JSON value can be one of 7 types. This class is a variant type supporting - these types. + A JSON value can be one of 7 types. This class is a variant type supporting + these types. - Use the Value if UTF8 and default allocator + Use the Value if UTF8 and default allocator - \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) - \tparam Allocator Allocator type for allocating memory of object, array and string. + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. */ -#pragma pack (push, 4) template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > class GenericValue { public: - //! Name-value pair in an object. - struct Member { - GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) - GenericValue<Encoding, Allocator> value; //!< value of member. - }; - - typedef Encoding EncodingType; //!< Encoding type from template parameter. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef Member* MemberIterator; //!< Member iterator for iterating in object. - typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object. - typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. - typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. - - //!@name Constructors and destructor. - //@{ - - //! Default constructor creates a null value. - GenericValue() : flags_(kNullFlag) {} - - //! Copy constructor is not permitted. + //! Name-value pair in an object. + typedef GenericMember<Encoding, Allocator> Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself. + typedef GenericArray<false, ValueType> Array; + typedef GenericArray<true, ValueType> ConstArray; + typedef GenericObject<false, ValueType> Object; + typedef GenericObject<true, ValueType> ConstObject; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents + } +#endif + private: - GenericValue(const GenericValue& rhs); + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template <typename StackAllocator> + GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template <typename StackAllocator> + GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); +#endif public: - //! Constructor with JSON value type. - /*! This creates a Value of specified type with default content. - \param type Type of the value. - \note Default content for number is zero. - */ - GenericValue(Type type) { - static const unsigned defaultFlags[7] = { - kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, - kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag - }; - RAPIDJSON_ASSERT(type <= kNumberType); - flags_ = defaultFlags[type]; - memset(&data_, 0, sizeof(data_)); - } - - //! Constructor for boolean value. - GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {} - - //! Constructor for int value. - GenericValue(int i) : flags_(kNumberIntFlag) { - data_.n.i64 = i; - if (i >= 0) - flags_ |= kUintFlag | kUint64Flag; - } - - //! Constructor for unsigned value. - GenericValue(unsigned u) : flags_(kNumberUintFlag) { - data_.n.u64 = u; - if (!(u & 0x80000000)) - flags_ |= kIntFlag | kInt64Flag; - } - - //! Constructor for int64_t value. - GenericValue(int64_t i64) : flags_(kNumberInt64Flag) { - data_.n.i64 = i64; - if (i64 >= 0) { - flags_ |= kNumberUint64Flag; - if (!(i64 & 0xFFFFFFFF00000000LL)) - flags_ |= kUintFlag; - if (!(i64 & 0xFFFFFFFF80000000LL)) - flags_ |= kIntFlag; - } - else if (i64 >= -2147483648LL) - flags_ |= kIntFlag; - } - - //! Constructor for uint64_t value. - GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) { - data_.n.u64 = u64; - if (!(u64 & 0x8000000000000000ULL)) - flags_ |= kInt64Flag; - if (!(u64 & 0xFFFFFFFF00000000ULL)) - flags_ |= kUintFlag; - if (!(u64 & 0xFFFFFFFF80000000ULL)) - flags_ |= kIntFlag; - } - - //! Constructor for double value. - GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; } - - //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s, SizeType length) { - RAPIDJSON_ASSERT(s != NULL); - flags_ = kConstStringFlag; - data_.s.str = s; - data_.s.length = length; - } - - //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); } - - //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); } - - //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); } - - //! Destructor. - /*! Need to destruct elements of array, members of object, or copy-string. - */ - ~GenericValue() { - if (Allocator::kNeedFree) { // Shortcut by Allocator's trait - switch(flags_) { - case kArrayFlag: - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) - v->~GenericValue(); - Allocator::Free(data_.a.elements); - break; - - case kObjectFlag: - for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { - m->name.~GenericValue(); - m->value.~GenericValue(); - } - Allocator::Free(data_.o.members); - break; - - case kCopyStringFlag: - Allocator::Free(const_cast<Ch*>(data_.s.str)); - break; - } - } - } - - //@} - - //!@name Assignment operators - //@{ - - //! Assignment with move semantics. - /*! \param rhs Source of the assignment. It will become a null value after assignment. - */ - GenericValue& operator=(GenericValue& rhs) { - RAPIDJSON_ASSERT(this != &rhs); - this->~GenericValue(); - memcpy(this, &rhs, sizeof(GenericValue)); - rhs.flags_ = kNullFlag; - return *this; - } - - //! Assignment with primitive types. - /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch* - \param value The value to be assigned. - */ - template <typename T> - GenericValue& operator=(T value) { - this->~GenericValue(); - new (this) GenericValue(value); - return *this; - } - //@} - - //!@name Type - //@{ - - Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); } - bool IsNull() const { return flags_ == kNullFlag; } - bool IsFalse() const { return flags_ == kFalseFlag; } - bool IsTrue() const { return flags_ == kTrueFlag; } - bool IsBool() const { return (flags_ & kBoolFlag) != 0; } - bool IsObject() const { return flags_ == kObjectFlag; } - bool IsArray() const { return flags_ == kArrayFlag; } - bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } - bool IsInt() const { return (flags_ & kIntFlag) != 0; } - bool IsUint() const { return (flags_ & kUintFlag) != 0; } - bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } - bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } - bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } - bool IsString() const { return (flags_ & kStringFlag) != 0; } - - //@} - - //!@name Null - //@{ - - GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } - - //@} - - //!@name Bool - //@{ - - bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } - GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } - - //@} - - //!@name Object - //@{ - - //! Set this value as an empty object. - GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } - - //! Get the value associated with the name. - /*! - \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. - Since 0.2, if the name is not correct, it will assert. - If user is unsure whether a member exists, user should use HasMember() first. - A better approach is to use the now public FindMember(). - */ - GenericValue& operator[](const Ch* name) { - if (Member* member = FindMember(name)) - return member->value; - else { - RAPIDJSON_ASSERT(false); // see above note - static GenericValue NullValue; - return NullValue; - } - } - const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; } - - //! Member iterators. - ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } - ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } - MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } - MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } - - //! Check whether a member exists in the object. - /*! - \note It is better to use FindMember() directly if you need the obtain the value as well. - */ - bool HasMember(const Ch* name) const { return FindMember(name) != 0; } - - //! Find member by name. - /*! - \return Return the member if exists. Otherwise returns null pointer. - */ - Member* FindMember(const Ch* name) { - RAPIDJSON_ASSERT(name); - RAPIDJSON_ASSERT(IsObject()); - - Object& o = data_.o; - for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) - if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) - return member; - - return 0; - } - const Member* FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); } - - //! Add a member (name-value pair) to the object. - /*! \param name A string value as name of member. - \param value Value of any type. - \param allocator Allocator for reallocating memory. - \return The value itself for fluent API. - \note The ownership of name and value will be transfered to this object if success. - */ - GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(name.IsString()); - Object& o = data_.o; - if (o.size >= o.capacity) { - if (o.capacity == 0) { - o.capacity = kDefaultObjectCapacity; - o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member)); - } - else { - SizeType oldCapacity = o.capacity; - o.capacity *= 2; - o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)); - } - } - o.members[o.size].name.RawAssign(name); - o.members[o.size].value.RawAssign(value); - o.size++; - return *this; - } - - GenericValue& AddMember(const Ch* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) { - GenericValue n(name, internal::StrLen(name), nameAllocator); - return AddMember(n, value, allocator); - } - - GenericValue& AddMember(const Ch* name, GenericValue& value, Allocator& allocator) { - GenericValue n(name, internal::StrLen(name)); - return AddMember(n, value, allocator); - } - - template <typename T> - GenericValue& AddMember(const Ch* name, T value, Allocator& allocator) { - GenericValue n(name, internal::StrLen(name)); - GenericValue v(value); - return AddMember(n, v, allocator); - } - - //! Remove a member in object by its name. - /*! \param name Name of member to be removed. - \return Whether the member existed. - \note Removing member is implemented by moving the last member. So the ordering of members is changed. - */ - bool RemoveMember(const Ch* name) { - RAPIDJSON_ASSERT(IsObject()); - if (Member* m = FindMember(name)) { - RAPIDJSON_ASSERT(data_.o.size > 0); - RAPIDJSON_ASSERT(data_.o.members != 0); - - Member* last = data_.o.members + (data_.o.size - 1); - if (data_.o.size > 1 && m != last) { - // Move the last one to this place - m->name = last->name; - m->value = last->value; - } - else { - // Only one left, just destroy - m->name.~GenericValue(); - m->value.~GenericValue(); - } - --data_.o.size; - return true; - } - return false; - } - - //@} - - //!@name Array - //@{ - - //! Set this value as an empty array. - GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } - - //! Get the number of elements in array. - SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } - - //! Get the capacity of array. - SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } - - //! Check whether the array is empty. - bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } - - //! Remove all elements in the array. - /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. - */ - void Clear() { - RAPIDJSON_ASSERT(IsArray()); - for (SizeType i = 0; i < data_.a.size; ++i) - data_.a.elements[i].~GenericValue(); - data_.a.size = 0; - } - - //! Get an element from array by index. - /*! \param index Zero-based index of element. - \note -\code -Value a(kArrayType); -a.PushBack(123); -int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. -int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. -int z = a[0u].GetInt(); // This works too. -\endcode - */ - GenericValue& operator[](SizeType index) { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(index < data_.a.size); - return data_.a.elements[index]; - } - const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; } - - //! Element iterator - ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } - ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } - ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } - ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); } - - //! Request the array to have enough capacity to store elements. - /*! \param newCapacity The capacity that the array at least need to have. - \param allocator The allocator for allocating memory. It must be the same one use previously. - \return The value itself for fluent API. - */ - GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { - RAPIDJSON_ASSERT(IsArray()); - if (newCapacity > data_.a.capacity) { - data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); - data_.a.capacity = newCapacity; - } - return *this; - } - - //! Append a value at the end of the array. - /*! \param value The value to be appended. - \param allocator The allocator for allocating memory. It must be the same one use previously. - \return The value itself for fluent API. - \note The ownership of the value will be transfered to this object if success. - \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. - */ - GenericValue& PushBack(GenericValue& value, Allocator& allocator) { - RAPIDJSON_ASSERT(IsArray()); - if (data_.a.size >= data_.a.capacity) - Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator); - data_.a.elements[data_.a.size++].RawAssign(value); - return *this; - } - - template <typename T> - GenericValue& PushBack(T value, Allocator& allocator) { - GenericValue v(value); - return PushBack(v, allocator); - } - - //! Remove the last element in the array. - GenericValue& PopBack() { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(!Empty()); - data_.a.elements[--data_.a.size].~GenericValue(); - return *this; - } - //@} - - //!@name Number - //@{ - - int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; } - unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; } - int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } - uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; } - - double GetDouble() const { - RAPIDJSON_ASSERT(IsNumber()); - if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. - if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double - if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double - if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) - RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) - } - - GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } - GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } - GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } - GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } - GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } - - //@} - - //!@name String - //@{ - - const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; } - - //! Get the length of string. - /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). - */ - SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; } - - //! Set this value as a string without copying source string. - /*! This version has better performance with supplied length, and also support string containing null character. - \param s source string pointer. - \param length The length of source string, excluding the trailing null terminator. - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; } - - //! Set this value as a string without copying source string. - /*! \param s source string pointer. - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); } - - //! Set this value as a string by copying from source string. - /*! This version has better performance with supplied length, and also support string containing null character. - \param s source string. - \param length The length of source string, excluding the trailing null terminator. - \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; } - - //! Set this value as a string by copying from source string. - /*! \param s source string. - \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; } - - //@} - - //! Generate events of this value to a Handler. - /*! This function adopts the GoF visitor pattern. - Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. - It can also be used to deep clone this value via GenericDocument, which is also a Handler. - \tparam Handler type of handler. - \param handler An object implementing concept Handler. - */ - template <typename Handler> - const GenericValue& Accept(Handler& handler) const { - switch(GetType()) { - case kNullType: handler.Null(); break; - case kFalseType: handler.Bool(false); break; - case kTrueType: handler.Bool(true); break; - - case kObjectType: - handler.StartObject(); - for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { - handler.String(m->name.data_.s.str, m->name.data_.s.length, false); - m->value.Accept(handler); - } - handler.EndObject(data_.o.size); - break; - - case kArrayType: - handler.StartArray(); - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) - v->Accept(handler); - handler.EndArray(data_.a.size); - break; - - case kStringType: - handler.String(data_.s.str, data_.s.length, false); - break; - - case kNumberType: - if (IsInt()) handler.Int(data_.n.i.i); - else if (IsUint()) handler.Uint(data_.n.u.u); - else if (IsInt64()) handler.Int64(data_.n.i64); - else if (IsUint64()) handler.Uint64(data_.n.u64); - else handler.Double(data_.n.d); - break; - } - return *this; - } + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template <typename SourceAllocator> + GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator) { + switch (rhs.GetType()) { + case kObjectType: { + SizeType count = rhs.data_.o.size; + Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member))); + const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer(); + for (SizeType i = 0; i < count; i++) { + new (&lm[i].name) GenericValue(rm[i].name, allocator); + new (&lm[i].value) GenericValue(rm[i].value, allocator); + } + data_.f.flags = kObjectFlag; + data_.o.size = data_.o.capacity = count; + SetMembersPointer(lm); + } + break; + case kArrayType: { + SizeType count = rhs.data_.a.size; + GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); + const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer(); + for (SizeType i = 0; i < count; i++) + new (&le[i]) GenericValue(re[i], allocator); + data_.f.flags = kArrayFlag; + data_.a.size = data_.a.capacity = count; + SetElementsPointer(le); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast<const Data*>(&rhs.data_); + } + else + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast<const Data*>(&rhs.data_); + break; + } + } + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template <typename T> + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if (i64 >= 0) { + data_.f.flags |= kNumberUint64Flag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + data_.f.flags |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for float value. + explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(e); + } + break; + + case kObjectFlag: + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + break; + + case kCopyStringFlag: + Allocator::Free(const_cast<Ch*>(GetStringPointer())); + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template <typename SourceAllocator> + GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs)); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template <typename SourceAllocator> + bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const { + typedef GenericValue<Encoding, SourceAllocator> RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template <typename SourceAllocator> + bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast<double>(u); + return (d >= 0.0) + && (d < static_cast<double>(std::numeric_limits<uint64_t>::max())) + && (u == static_cast<uint64_t>(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast<double>(i); + return (d >= static_cast<double>(std::numeric_limits<int64_t>::min())) + && (d < static_cast<double>(std::numeric_limits<int64_t>::max())) + && (i == static_cast<int64_t>(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast<double>(-std::numeric_limits<float>::max()) + || a > static_cast<double>(std::numeric_limits<float>::max())) + return false; + double b = static_cast<double>(static_cast<float>(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template <typename SourceAllocator> + GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); + } + } + template <typename SourceAllocator> + const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template <typename SourceAllocator> + bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template <typename SourceAllocator> + MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + + ObjectData& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)))); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); + } + } + Member* members = GetMembersPointer(); + members[o.size].name.RawAssign(name); + members[o.size].value.RawAssign(value); + o.size++; + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + + MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) + *m = *last; // Move the last one to this place + else + m->~Member(); // Only one left, just destroy + --data_.o.size; + return m; + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + + MemberIterator pos = MemberBegin() + (first - MemberBegin()); + for (MemberIterator itr = pos; itr != last; ++itr) + itr->~Member(); + std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member)); + data_.o.size -= static_cast<SizeType>(last - first); + return pos; + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack<StringRefType>(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast<SizeType>(last - first); + return pos; + } + + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast<float>(GetDouble()); + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } +#endif + + //@} + + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch> + */ + template <typename T> + bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); } + + template <typename T> + T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } + + template <typename T> + T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); } + + template<typename T> + ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } + + template<typename T> + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template <typename Handler> + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) + return false; + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; + for (const GenericValue* v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else return handler.Uint64(data_.n.u64); + } + } private: - template <typename, typename> - friend class GenericDocument; - - enum { - kBoolFlag = 0x100, - kNumberFlag = 0x200, - kIntFlag = 0x400, - kUintFlag = 0x800, - kInt64Flag = 0x1000, - kUint64Flag = 0x2000, - kDoubleFlag = 0x4000, - kStringFlag = 0x100000, - kCopyFlag = 0x200000, - - // Initial flags of different types. - kNullFlag = kNullType, - kTrueFlag = kTrueType | kBoolFlag, - kFalseFlag = kFalseType | kBoolFlag, - kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, - kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, - kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, - kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, - kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, - kConstStringFlag = kStringType | kStringFlag, - kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, - kObjectFlag = kObjectType, - kArrayFlag = kArrayType, - - kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler - }; - - static const SizeType kDefaultArrayCapacity = 16; - static const SizeType kDefaultObjectCapacity = 16; - - struct String { - const Ch* str; - SizeType length; - unsigned hashcode; //!< reserved - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - // By using proper binary layout, retrieval of different integer types do not need conversions. - union Number { + template <typename, typename> friend class GenericValue; + template <typename, typename, typename> friend class GenericDocument; + + enum { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + + struct String { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); } + inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN - struct I { - int i; - char padding[4]; - }i; - struct U { - unsigned u; - char padding2[4]; - }u; + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; #else - struct I { - char padding[4]; - int i; - }i; - struct U { - char padding2[4]; - unsigned u; - }u; -#endif - int64_t i64; - uint64_t u64; - double d; - }; // 8 bytes - - struct Object { - Member* members; - SizeType size; - SizeType capacity; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - struct Array { - GenericValue<Encoding, Allocator>* elements; - SizeType size; - SizeType capacity; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - union Data { - String s; - Number n; - Object o; - Array a; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - // Initialize this value as array with initial data, without calling destructor. - void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) { - flags_ = kArrayFlag; - data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue)); - memcpy(data_.a.elements, values, count * sizeof(GenericValue)); - data_.a.size = data_.a.capacity = count; - } - - //! Initialize this value as object with initial data, without calling destructor. - void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) { - flags_ = kObjectFlag; - data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member)); - memcpy(data_.o.members, members, count * sizeof(Member)); - data_.o.size = data_.o.capacity = count; - } - - //! Initialize this value as constant string, without calling destructor. - void SetStringRaw(const Ch* s, SizeType length) { - RAPIDJSON_ASSERT(s != NULL); - flags_ = kConstStringFlag; - data_.s.str = s; - data_.s.length = length; - } - - //! Initialize this value as copy string with initial data, without calling destructor. - void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) { - RAPIDJSON_ASSERT(s != NULL); - flags_ = kCopyStringFlag; - data_.s.str = (Ch *)allocator.Malloc((length + 1) * sizeof(Ch)); - data_.s.length = length; - memcpy(const_cast<Ch*>(data_.s.str), s, length * sizeof(Ch)); - const_cast<Ch*>(data_.s.str)[length] = '\0'; - } - - //! Assignment without calling destructor - void RawAssign(GenericValue& rhs) { - memcpy(this, &rhs, sizeof(GenericValue)); - rhs.flags_ = kNullFlag; - } - - Data data_; - unsigned flags_; + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct ObjectData { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct ArrayData { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + data_.f.flags = kArrayFlag; + if (count) { + GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(e, values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { + Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member))); + SetMembersPointer(m); + std::memcpy(m, members, count * sizeof(Member)); + } + else + SetMembersPointer(0); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } + + template <typename SourceAllocator> + bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; }; -#pragma pack (pop) -//! Value with UTF8 encoding. +//! GenericValue with UTF8 encoding typedef GenericValue<UTF8<> > Value; /////////////////////////////////////////////////////////////////////////////// @@ -694,150 +2064,539 @@ typedef GenericValue<UTF8<> > Value; //! A document for parsing JSON text as DOM. /*! - \implements Handler - \tparam Encoding encoding for both parsing and string storage. - \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing. + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. */ -template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > +template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator> class GenericDocument : public GenericValue<Encoding, Allocator> { public: - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. - - //! Constructor - /*! \param allocator Optional allocator for allocating stack memory. - \param stackCapacity Initial capacity of stack in bytes. - */ - GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} - - //! Parse JSON text from an input stream. - /*! \tparam parseFlags Combination of ParseFlag. - \param stream Input stream to be parsed. - \return The document itself for fluent API. - */ - template <unsigned parseFlags, typename SourceEncoding, typename InputStream> - GenericDocument& ParseStream(InputStream& is) { - ValueType::SetNull(); // Remove existing root if exist - GenericReader<SourceEncoding, Encoding, Allocator> reader; - if (reader.template Parse<parseFlags>(is, *this)) { - RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13. - parseError_ = 0; - errorOffset_ = 0; - } - else { - parseError_ = reader.GetParseError(); - errorOffset_ = reader.GetErrorOffset(); - ClearStack(); - } - return *this; - } - - //! Parse JSON text from a mutable string. - /*! \tparam parseFlags Combination of ParseFlag. - \param str Mutable zero-terminated string to be parsed. - \return The document itself for fluent API. - */ - template <unsigned parseFlags, typename SourceEncoding> - GenericDocument& ParseInsitu(Ch* str) { - GenericInsituStringStream<Encoding> s(str); - return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s); - } - - template <unsigned parseFlags> - GenericDocument& ParseInsitu(Ch* str) { - return ParseInsitu<parseFlags, Encoding>(str); - } - - //! Parse JSON text from a read-only string. - /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag). - \param str Read-only zero-terminated string to be parsed. - */ - template <unsigned parseFlags, typename SourceEncoding> - GenericDocument& Parse(const Ch* str) { - RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); - GenericStringStream<SourceEncoding> s(str); - return ParseStream<parseFlags, SourceEncoding>(s); - } - - template <unsigned parseFlags> - GenericDocument& Parse(const Ch* str) { - return Parse<parseFlags, Encoding>(str); - } - - //! Whether a parse error was occured in the last parsing. - bool HasParseError() const { return parseError_ != 0; } - - //! Get the message of parsing error. - const char* GetParseError() const { return parseError_; } - - //! Get the offset in character of the parsing error. - size_t GetErrorOffset() const { return errorOffset_; } - - //! Get the allocator of this document. - Allocator& GetAllocator() { return stack_.GetAllocator(); } - - //! Get the capacity of stack in bytes. - size_t GetStackCapacity() const { return stack_.GetCapacity(); } - -//private: - //friend class GenericReader<Encoding>; // for Reader to call the following private handler functions - - // Implementation of Handler - void Null() { new (stack_.template Push<ValueType>()) ValueType(); } - void Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); } - void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); } - void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); } - void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); } - void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); } - void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); } - - void String(const Ch* str, SizeType length, bool copy) { - if (copy) - new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); - else - new (stack_.template Push<ValueType>()) ValueType(str, length); - } - - void StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); } - - void EndObject(SizeType memberCount) { - typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount); - stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); - } - - void StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); } - - void EndArray(SizeType elementCount) { - ValueType* elements = stack_.template Pop<ValueType>(elementCount); - stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator()); - } + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward<ValueType>(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template <typename Generator> + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document + } + return *this; + } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags, typename SourceEncoding, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + GenericReader<SourceEncoding, Encoding, StackAllocator> reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse<parseFlags>(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<parseFlags, Encoding, InputStream>(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags> + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream<Encoding> s(str); + return ParseStream<parseFlags | kParseInsituFlag>(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu<kParseDefaultFlags>(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream<SourceEncoding> s(str); + return ParseStream<parseFlags, SourceEncoding>(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template <unsigned parseFlags> + GenericDocument& Parse(const Ch* str) { + return Parse<parseFlags, Encoding>(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse<kParseDefaultFlags>(str); + } + + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream<SourceEncoding, MemoryStream> is(ms); + ParseStream<parseFlags, SourceEncoding>(is); + return *this; + } + + template <unsigned parseFlags> + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse<parseFlags, Encoding>(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse<kParseDefaultFlags>(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse<parseFlags, SourceEncoding>(str.c_str()); + } + + template <unsigned parseFlags> + GenericDocument& Parse(const std::basic_string<Ch>& str) { + return Parse<parseFlags, Encoding>(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string<Ch>& str) { + return Parse<kParseDefaultFlags>(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + // template <typename,typename,typename> friend class GenericReader; // for parsing + template <typename, typename> friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount); + stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop<ValueType>(elementCount); + stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } private: - // Prohibit assignment - GenericDocument& operator=(const GenericDocument&); - - void ClearStack() { - if (Allocator::kNeedFree) - while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) - (stack_.template Pop<ValueType>(1))->~ValueType(); - else - stack_.Clear(); - } - - static const size_t kDefaultStackCapacity = 1024; - internal::Stack<Allocator> stack_; - const char* parseError_; - size_t errorOffset_; + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop<ValueType>(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack<StackAllocator> stack_; + ParseResult parseResult_; }; +//! GenericDocument with UTF8 encoding typedef GenericDocument<UTF8<> > Document; -} // namespace rapidjson +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template <bool Const, typename ValueT> +class GenericArray { +public: + typedef GenericArray<true, ValueT> ConstArray; + typedef GenericArray<false, ValueT> Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + + template <typename, typename> + friend class GenericValue; + + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } +#endif -#ifdef _MSC_VER -#pragma warning(pop) +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template <bool Const, typename ValueT> +class GenericObject { +public: + typedef GenericObject<true, ValueT> ConstObject; + typedef GenericObject<false, ValueT> Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template <typename, typename> + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + SizeType MemberCount() const { return value_.MemberCount(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template <typename T> ValueType& operator[](T* name) const { return value_[name]; } + template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); } +#endif + template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); } +#endif + template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +#ifdef _MINWINDEF_ // see: http://stackoverflow.com/questions/22744262/cant-call-stdmax-because-minwindef-h-defines-max +#ifndef NOMINMAX +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif #endif +RAPIDJSON_DIAG_POP #endif // RAPIDJSON_DOCUMENT_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/encodedstream.h b/Source/ThirdParty/rapidjson/include/rapidjson/encodedstream.h index 1f7bb5cf84..223601c059 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/encodedstream.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/encodedstream.h @@ -1,250 +1,299 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_ENCODEDSTREAM_H_ #define RAPIDJSON_ENCODEDSTREAM_H_ -#include "rapidjson.h" +#include "stream.h" +#include "memorystream.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif -namespace rapidjson { +RAPIDJSON_NAMESPACE_BEGIN //! Input byte stream wrapper with a statically bound encoding. /*! - \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. - \tparam InputByteStream Type of input byte stream. For example, FileReadStream. + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. */ template <typename Encoding, typename InputByteStream> class EncodedInputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); public: - typedef typename Encoding::Ch Ch; + typedef typename Encoding::Ch Ch; - EncodedInputStream(InputByteStream& is) : is_(is) { - current_ = Encoding::TakeBOM(is_); - } + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } - Ch Peek() const { return current_; } - Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } - size_t Tell() const { return is_.Tell(); } + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } - // Not implemented - void Put(Ch c) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } private: - // Prohibit assignment for VC C4512 warning - EncodedInputStream& operator=(const EncodedInputStream&); + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); - InputByteStream& is_; - Ch current_; + InputByteStream& is_; + Ch current_; +}; + +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream<UTF8<>, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); }; //! Output byte stream wrapper with statically bound encoding. /*! - \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. - \tparam InputByteStream Type of input byte stream. For example, FileWriteStream. + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. */ template <typename Encoding, typename OutputByteStream> class EncodedOutputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); public: - typedef typename Encoding::Ch Ch; + typedef typename Encoding::Ch Ch; - EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { - if (putBOM) - Encoding::PutBOM(os_); - } + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } - void Put(Ch c) { Encoding::Put(os_, c); } - void Flush() { os_.Flush(); } + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } - // Not implemented - Ch Peek() const { RAPIDJSON_ASSERT(false); } - Ch Take() { RAPIDJSON_ASSERT(false); } - size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } private: - // Prohibit assignment for VC C4512 warning - EncodedOutputStream& operator=(const EncodedOutputStream&); + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); - OutputByteStream& os_; + OutputByteStream& os_; }; #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x //! Input stream wrapper with dynamically bound encoding and automatic encoding detection. /*! - \tparam CharType Type of character for reading. - \tparam InputByteStream type of input byte stream to be wrapped. + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. */ template <typename CharType, typename InputByteStream> class AutoUTFInputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); public: - typedef CharType Ch; - - //! Constructor. - /*! - \param is input stream to be wrapped. - \param type UTF encoding type if it is not detected from the stream. - */ - AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { - DetectType(); - static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; - takeFunc_ = f[type_]; - current_ = takeFunc_(*is_); - } - - UTFType GetType() const { return type_; } - bool HasBOM() const { return hasBOM_; } - - Ch Peek() const { return current_; } - Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } - size_t Tell() const { return is_->Tell(); } - - // Not implemented - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } private: - // Detect encoding type with BOM or RFC 4627 - void DetectType() { - // BOM (Byte Order Mark): - // 00 00 FE FF UTF-32BE - // FF FE 00 00 UTF-32LE - // FE FF UTF-16BE - // FF FE UTF-16LE - // EF BB BF UTF-8 - - const unsigned char* c = (const unsigned char *)is_->Peek4(); - if (!c) - return; - - unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); - hasBOM_ = false; - if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } - else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } - else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } - else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } - else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } - - // RFC 4627: Section 3 - // "Since the first two characters of a JSON text will always be ASCII - // characters [RFC0020], it is possible to determine whether an octet - // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking - // at the pattern of nulls in the first four octets." - // 00 00 00 xx UTF-32BE - // 00 xx 00 xx UTF-16BE - // xx 00 00 00 UTF-32LE - // xx 00 xx 00 UTF-16LE - // xx xx xx xx UTF-8 - - if (!hasBOM_) { - unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); - switch (pattern) { - case 0x08: type_ = kUTF32BE; break; - case 0x0A: type_ = kUTF16BE; break; - case 0x01: type_ = kUTF32LE; break; - case 0x05: type_ = kUTF16LE; break; - case 0x0F: type_ = kUTF8; break; - } - } - - // RUntime check whether the size of character type is sufficient. It only perform checks with assertion. - switch (type_) { - case kUTF8: - // Do nothing - break; - case kUTF16LE: - case kUTF16BE: - RAPIDJSON_ASSERT(sizeof(Ch) >= 2); - break; - case kUTF32LE: - case kUTF32BE: - RAPIDJSON_ASSERT(sizeof(Ch) >= 4); - break; - } - } - - typedef Ch (*TakeFunc)(InputByteStream& is); - InputByteStream* is_; - UTFType type_; - Ch current_; - TakeFunc takeFunc_; - bool hasBOM_; + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; }; //! Output stream wrapper with dynamically bound encoding and automatic encoding detection. /*! - \tparam CharType Type of character for writing. - \tparam InputByteStream type of output byte stream to be wrapped. + \tparam CharType Type of character for writing. + \tparam OutputByteStream type of output byte stream to be wrapped. */ template <typename CharType, typename OutputByteStream> class AutoUTFOutputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); public: - typedef CharType Ch; - - //! Constructor. - /*! - \param os output stream to be wrapped. - \param type UTF encoding type. - \param putBOM Whether to write BOM at the beginning of the stream. - */ - AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { - // RUntime check whether the size of character type is sufficient. It only perform checks with assertion. - switch (type_) { - case kUTF16LE: - case kUTF16BE: - RAPIDJSON_ASSERT(sizeof(Ch) >= 2); - break; - case kUTF32LE: - case kUTF32BE: - RAPIDJSON_ASSERT(sizeof(Ch) >= 4); - break; - case kUTF8: - // Do nothing - break; - } - - static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; - putFunc_ = f[type_]; - - if (putBOM) - PutBOM(); - } - - UTFType GetType() const { return type_; } - - void Put(Ch c) { putFunc_(*os_, c); } - void Flush() { os_->Flush(); } - - // Not implemented - Ch Peek() const { RAPIDJSON_ASSERT(false); } - Ch Take() { RAPIDJSON_ASSERT(false); } - size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } private: - void PutBOM() { - typedef void (*PutBOMFunc)(OutputByteStream&); - static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; - f[type_](*os_); - } + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } - typedef void (*PutFunc)(OutputByteStream&, Ch); + typedef void (*PutFunc)(OutputByteStream&, Ch); - OutputByteStream* os_; - UTFType type_; - PutFunc putFunc_; + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; }; #undef RAPIDJSON_ENCODINGS_FUNC -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/encodings.h b/Source/ThirdParty/rapidjson/include/rapidjson/encodings.h index 33fcc3c938..ed7d44d369 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/encodings.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/encodings.h @@ -1,58 +1,84 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_ENCODINGS_H_ #define RAPIDJSON_ENCODINGS_H_ #include "rapidjson.h" -namespace rapidjson { +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN /////////////////////////////////////////////////////////////////////////////// // Encoding /*! \class rapidjson::Encoding - \brief Concept for encoding of Unicode characters. + \brief Concept for encoding of Unicode characters. \code concept Encoding { - typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. - - //! \brief Encode a Unicode codepoint to an output stream. - //! \param os Output stream. - //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. - template<typename OutputStream> - static void Encode(OutputStream& os, unsigned codepoint); - - //! \brief Decode a Unicode codepoint from an input stream. - //! \param is Input stream. - //! \param codepoint Output of the unicode codepoint. - //! \return true if a valid codepoint can be decoded from the stream. - template <typename InputStream> - static bool Decode(InputStream& is, unsigned* codepoint); - - //! \brief Validate one Unicode codepoint from an encoded stream. - //! \param is Input stream to obtain codepoint. - //! \param os Output for copying one codepoint. - //! \return true if it is valid. - //! \note This function just validating and copying the codepoint without actually decode it. - template <typename InputStream, typename OutputStream> - static bool Validate(InputStream& is, OutputStream& os); - - // The following functions are deal with byte streams. - - //! Take a character from input byte stream, skip BOM if exist. - template <typename InputByteStream> - static CharType TakeBOM(InputByteStream& is); - - //! Take a character from input byte stream. - template <typename InputByteStream> - static Ch Take(InputByteStream& is); - - //! Put BOM to output byte stream. - template <typename OutputByteStream> - static void PutBOM(OutputByteStream& os); - - //! Put a character to output byte stream. - template <typename OutputByteStream> - static void Put(OutputByteStream& os, Ch c); + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template <typename InputByteStream> + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c); }; \endcode */ @@ -62,139 +88,169 @@ concept Encoding { //! UTF-8 encoding. /*! http://en.wikipedia.org/wiki/UTF-8 - http://tools.ietf.org/html/rfc3629 - \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. - \implements Encoding + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept */ template<typename CharType = char> struct UTF8 { - typedef CharType Ch; - - template<typename OutputStream> - static void Encode(OutputStream& os, unsigned codepoint) { - if (codepoint <= 0x7F) - os.Put(codepoint & 0xFF); - else if (codepoint <= 0x7FF) { - os.Put(0xC0 | ((codepoint >> 6) & 0xFF)); - os.Put(0x80 | ((codepoint & 0x3F))); - } - else if (codepoint <= 0xFFFF) { - os.Put(0xE0 | ((codepoint >> 12) & 0xFF)); - os.Put(0x80 | ((codepoint >> 6) & 0x3F)); - os.Put(0x80 | (codepoint & 0x3F)); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - os.Put(0xF0 | ((codepoint >> 18) & 0xFF)); - os.Put(0x80 | ((codepoint >> 12) & 0x3F)); - os.Put(0x80 | ((codepoint >> 6) & 0x3F)); - os.Put(0x80 | (codepoint & 0x3F)); - } - } - - template <typename InputStream> - static bool Decode(InputStream& is, unsigned* codepoint) { -#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) -#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) +#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) - Ch c = is.Take(); - if (!(c & 0x80)) { - *codepoint = (unsigned char)c; - return true; - } - - unsigned char type = GetRange((unsigned char)c); - *codepoint = (0xFF >> type) & (unsigned char)c; - bool result = true; - switch (type) { - case 2: TAIL(); return result; - case 3: TAIL(); TAIL(); return result; - case 4: COPY(); TRANS(0x50); TAIL(); return result; - case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; - case 6: TAIL(); TAIL(); TAIL(); return result; - case 10: COPY(); TRANS(0x20); TAIL(); return result; - case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; - default: return false; - } + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast<unsigned char>(c); + return true; + } + + unsigned char type = GetRange(static_cast<unsigned char>(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c); + } + bool result = true; + switch (type) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } #undef COPY #undef TRANS #undef TAIL - } + } - template <typename InputStream, typename OutputStream> - static bool Validate(InputStream& is, OutputStream& os) { + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { #define COPY() os.Put(c = is.Take()) -#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) - Ch c; - COPY(); - if (!(c & 0x80)) - return true; - - bool result = true; - switch (GetRange((unsigned char)c)) { - case 2: TAIL(); return result; - case 3: TAIL(); TAIL(); return result; - case 4: COPY(); TRANS(0x50); TAIL(); return result; - case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; - case 6: TAIL(); TAIL(); TAIL(); return result; - case 10: COPY(); TRANS(0x20); TAIL(); return result; - case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; - default: return false; - } + Ch c; + COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast<unsigned char>(c))) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } #undef COPY #undef TRANS #undef TAIL - } - - static unsigned char GetRange(unsigned char c) { - // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ - // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. - static const unsigned char type[] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, - }; - return type[c]; - } - - template <typename InputByteStream> - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - Ch c = Take(is); - if ((unsigned char)c != 0xEFu) return c; - c = is.Take(); - if ((unsigned char)c != 0xBBu) return c; - c = is.Take(); - if ((unsigned char)c != 0xBFu) return c; - c = is.Take(); - return c; - } - - template <typename InputByteStream> - static Ch Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); - } - - template <typename OutputByteStream> - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); - } - - template <typename OutputByteStream> - static void Put(OutputByteStream& os, Ch c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast<typename OutputByteStream::Ch>(c)); - } + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast<unsigned char>(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast<unsigned char>(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast<unsigned char>(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast<Ch>(is.Take()); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c)); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -202,129 +258,149 @@ struct UTF8 { //! UTF-16 encoding. /*! http://en.wikipedia.org/wiki/UTF-16 - http://tools.ietf.org/html/rfc2781 - \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. - \implements Encoding + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept - \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. - For streaming, use UTF16LE and UTF16BE, which handle endianness. + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. */ template<typename CharType = wchar_t> struct UTF16 { - typedef CharType Ch; - RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); - - template<typename OutputStream> - static void Encode(OutputStream& os, unsigned codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); - if (codepoint <= 0xFFFF) { - RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair - os.Put(static_cast<typename OutputStream::Ch>(codepoint)); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - unsigned v = codepoint - 0x10000; - os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); - os.Put((v & 0x3FF) | 0xDC00); - } - } - - template <typename InputStream> - static bool Decode(InputStream& is, unsigned* codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); - Ch c = is.Take(); - if (c < 0xD800 || c > 0xDFFF) { - *codepoint = c; - return true; - } - else if (c <= 0xDBFF) { - *codepoint = (c & 0x3FF) << 10; - c = is.Take(); - *codepoint |= (c & 0x3FF); - *codepoint += 0x10000; - return c >= 0xDC00 && c <= 0xDFFF; - } - return false; - } - - template <typename InputStream, typename OutputStream> - static bool Validate(InputStream& is, OutputStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); - Ch c; - os.Put(c = is.Take()); - if (c < 0xD800 || c > 0xDFFF) - return true; - else if (c <= 0xDBFF) { - os.Put(c = is.Take()); - return c >= 0xDC00 && c <= 0xDFFF; - } - return false; - } + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00)); + } + } + + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00)); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + typename InputStream::Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = static_cast<unsigned>(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast<unsigned>(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + typename InputStream::Ch c; + os.Put(static_cast<typename OutputStream::Ch>(c = is.Take())); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } }; //! UTF-16 little endian encoding. template<typename CharType = wchar_t> struct UTF16LE : UTF16<CharType> { - template <typename InputByteStream> - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return (unsigned short)c == 0xFEFFu ? Take(is) : c; - } - - template <typename InputByteStream> - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take(); - c |= (unsigned char)is.Take() << 8; - return c; - } - - template <typename OutputByteStream> - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); - } - - template <typename OutputByteStream> - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(c & 0xFFu); - os.Put((c >> 8) & 0xFFu); - } + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<uint8_t>(is.Take()); + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu)); + } }; //! UTF-16 big endian encoding. template<typename CharType = wchar_t> struct UTF16BE : UTF16<CharType> { - template <typename InputByteStream> - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return (unsigned short)c == 0xFEFFu ? Take(is) : c; - } - - template <typename InputByteStream> - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take(); - return c; - } - - template <typename OutputByteStream> - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFEu); os.Put(0xFFu); - } - - template <typename OutputByteStream> - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put((c >> 8) & 0xFFu); - os.Put(c & 0xFFu); - } + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<uint8_t>(is.Take()); + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu)); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -332,111 +408,192 @@ struct UTF16BE : UTF16<CharType> { //! UTF-32 encoding. /*! http://en.wikipedia.org/wiki/UTF-32 - \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. - \implements Encoding + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept - \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. - For streaming, use UTF32LE and UTF32BE, which handle endianness. + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. */ template<typename CharType = unsigned> struct UTF32 { - typedef CharType Ch; - RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); - - template<typename OutputStream> - static void Encode(OutputStream& os, unsigned codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - os.Put(codepoint); - } - - template <typename InputStream> - static bool Decode(InputStream& is, unsigned* codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); - Ch c = is.Take(); - *codepoint = c; - return c <= 0x10FFFF; - } - - template <typename InputStream, typename OutputStream> - static bool Validate(InputStream& is, OutputStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); - Ch c; - os.Put(c = is.Take()); - return c <= 0x10FFFF; - } + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } }; //! UTF-32 little endian enocoding. template<typename CharType = unsigned> struct UTF32LE : UTF32<CharType> { - template <typename InputByteStream> - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return (unsigned)c == 0x0000FEFFu ? Take(is) : c; - } - - template <typename InputByteStream> - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take(); - c |= (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take() << 16; - c |= (unsigned char)is.Take() << 24; - return c; - } - - template <typename OutputByteStream> - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u); - } - - template <typename OutputByteStream> - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(c & 0xFFu); - os.Put((c >> 8) & 0xFFu); - os.Put((c >> 16) & 0xFFu); - os.Put((c >> 24) & 0xFFu); - } + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<uint8_t>(is.Take()); + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24; + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu)); + } }; //! UTF-32 big endian encoding. template<typename CharType = unsigned> struct UTF32BE : UTF32<CharType> { - template <typename InputByteStream> - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return (unsigned)c == 0x0000FEFFu ? Take(is) : c; - } - - template <typename InputByteStream> - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take() << 24; - c |= (unsigned char)is.Take() << 16; - c |= (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take(); - return c; - } - - template <typename OutputByteStream> - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); - } - - template <typename OutputByteStream> - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put((c >> 24) & 0xFFu); - os.Put((c >> 16) & 0xFFu); - os.Put((c >> 8) & 0xFFu); - os.Put(c & 0xFFu); - } + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())); + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template<typename CharType = char> +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast<Ch>(codepoint & 0xFF)); + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast<uint8_t>(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast<uint8_t>(is.Take()); + os.Put(static_cast<typename OutputStream::Ch>(c)); + return c <= 0x7F; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast<uint8_t>(Take(is)); + return static_cast<Ch>(c); + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast<Ch>(is.Take()); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c)); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -444,11 +601,11 @@ struct UTF32BE : UTF32<CharType> { //! Runtime-specified UTF encoding type of a stream. enum UTFType { - kUTF8 = 0, //!< UTF-8. - kUTF16LE = 1, //!< UTF-16 little endian. - kUTF16BE = 2, //!< UTF-16 big endian. - kUTF32LE = 3, //!< UTF-32 little endian. - kUTF32BE = 4, //!< UTF-32 big endian. + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. }; //! Dynamically select encoding according to stream's runtime-specified UTF encoding type. @@ -456,30 +613,39 @@ enum UTFType { */ template<typename CharType> struct AutoUTF { - typedef CharType Ch; + typedef CharType Ch; + + enum { supportUnicode = 1 }; #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x - template<typename OutputStream> - RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { - typedef void (*EncodeFunc)(OutputStream&, unsigned); - static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; - (*f[os.GetType()])(os, codepoint); - } - - template <typename InputStream> - RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { - typedef bool (*DecodeFunc)(InputStream&, unsigned*); - static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; - return (*f[is.GetType()])(is, codepoint); - } - - template <typename InputStream, typename OutputStream> - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { - typedef bool (*ValidateFunc)(InputStream&, OutputStream&); - static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; - return (*f[is.GetType()])(is, os); - } + template<typename OutputStream> + RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template<typename OutputStream> + RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; + (*f[os.GetType()])(os, codepoint); + } + + template <typename InputStream> + RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template <typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } #undef RAPIDJSON_ENCODINGS_FUNC }; @@ -490,38 +656,61 @@ struct AutoUTF { //! Encoding conversion. template<typename SourceEncoding, typename TargetEncoding> struct Transcoder { - //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. - template<typename InputStream, typename OutputStream> - RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { - unsigned codepoint; - if (!SourceEncoding::Decode(is, &codepoint)) - return false; - TargetEncoding::Encode(os, codepoint); - return true; - } - - //! Validate one Unicode codepoint from an encoded stream. - template<typename InputStream, typename OutputStream> - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { - return Transcode(is, os); // Since source/target encoding is different, must transcode. - } + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } }; +// Forward declaration. +template<typename Stream> +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + //! Specialization of Transcoder with same source and target encoding. template<typename Encoding> struct Transcoder<Encoding, Encoding> { - template<typename InputStream, typename OutputStream> - RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { - os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. - return true; - } - - template<typename InputStream, typename OutputStream> - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { - return Encoding::Validate(is, os); // source/target encoding are the same - } + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } }; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_ENCODINGS_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/filereadstream.h b/Source/ThirdParty/rapidjson/include/rapidjson/filereadstream.h index 2c97c67047..b56ea13b34 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/filereadstream.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/filereadstream.h @@ -1,74 +1,99 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_FILEREADSTREAM_H_ #define RAPIDJSON_FILEREADSTREAM_H_ -#include "rapidjson.h" +#include "stream.h" #include <cstdio> -namespace rapidjson { +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN //! File byte stream for input using fread(). /*! - \implements Stream + \note implements Stream concept */ class FileReadStream { public: - typedef char Ch; //!< Character type (byte). + typedef char Ch; //!< Character type (byte). - //! Constructor. - /*! - \param fp File pointer opened for read. - \param buffer user-supplied buffer. - \param bufferSize size of buffer in bytes. Must >=4 bytes. - */ - FileReadStream(FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { - RAPIDJSON_ASSERT(fp_ != 0); - RAPIDJSON_ASSERT(bufferSize >= 4); - Read(); - } + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } - Ch Peek() const { return *current_; } - Ch Take() { Ch c = *current_; Read(); return c; } - size_t Tell() const { return count_ + (current_ - buffer_); } + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } - // Not implemented - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } - // For encoding detection only. - const Ch* Peek4() const { - return (current_ + 4 <= bufferLast_) ? current_ : 0; - } + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 <= bufferLast_) ? current_ : 0; + } private: - void Read() { - if (current_ < bufferLast_) - ++current_; - else if (!eof_) { - count_ += readCount_; - readCount_ = fread(buffer_, 1, bufferSize_, fp_); - bufferLast_ = buffer_ + readCount_ - 1; - current_ = buffer_; + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; - if (readCount_ < bufferSize_) { - buffer_[readCount_] = '\0'; - ++bufferLast_; - eof_ = true; - } - } - } + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } - FILE* fp_; - Ch *buffer_; - size_t bufferSize_; - Ch *bufferLast_; - Ch *current_; - size_t readCount_; - size_t count_; //!< Number of characters read - bool eof_; + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; }; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/filestream.h b/Source/ThirdParty/rapidjson/include/rapidjson/filestream.h deleted file mode 100644 index d003029f89..0000000000 --- a/Source/ThirdParty/rapidjson/include/rapidjson/filestream.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef RAPIDJSON_FILESTREAM_H_ -#define RAPIDJSON_FILESTREAM_H_ - -#include "rapidjson.h" -#include <cstdio> - -namespace rapidjson { - -//! (Depreciated) Wrapper of C file stream for input or output. -/*! - This simple wrapper does not check the validity of the stream. - \implements Stream - \deprecated { This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead. } -*/ -class FileStream { -public: - typedef char Ch; //!< Character type. Only support char. - - FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); } - char Peek() const { return current_; } - char Take() { char c = current_; Read(); return c; } - size_t Tell() const { return count_; } - void Put(char c) { fputc(c, fp_); } - void Flush() { fflush(fp_); } - - // Not implemented - char* PutBegin() { return 0; } - size_t PutEnd(char*) { return 0; } - -private: - void Read() { - RAPIDJSON_ASSERT(fp_ != 0); - int c = fgetc(fp_); - if (c != EOF) { - current_ = (char)c; - count_++; - } - else if (current_ != '\0') - current_ = '\0'; - } - - FILE* fp_; - char current_; - size_t count_; -}; - -} // namespace rapidjson - -#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/filewritestream.h b/Source/ThirdParty/rapidjson/include/rapidjson/filewritestream.h index b3d9de3d56..6378dd60ed 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/filewritestream.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/filewritestream.h @@ -1,73 +1,104 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_FILEWRITESTREAM_H_ #define RAPIDJSON_FILEWRITESTREAM_H_ -#include "rapidjson.h" +#include "stream.h" #include <cstdio> -namespace rapidjson { +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN //! Wrapper of C file stream for input using fread(). /*! - \implements Stream + \note implements Stream concept */ class FileWriteStream { public: - typedef char Ch; //!< Character type. Only support char. - - FileWriteStream(FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { - RAPIDJSON_ASSERT(fp_ != 0); - } - - void Put(char c) { - if (current_ >= bufferEnd_) - Flush(); - - *current_++ = c; - } - - void PutN(char c, size_t n) { - size_t avail = bufferEnd_ - current_; - while (n > avail) { - memset(current_, c, avail); - current_ += avail; - Flush(); - n -= avail; - avail = bufferEnd_ - current_; - } - - if (n > 0) { - memset(current_, c, n); - current_ += n; - } - } - - void Flush() { - if (current_ != buffer_) { - fwrite(buffer_, 1, current_ - buffer_, fp_); - current_ = buffer_; - } - } - - // Not implemented - char Peek() const { RAPIDJSON_ASSERT(false); return 0; } - char Take() { RAPIDJSON_ASSERT(false); return 0; } - size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } - char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast<size_t>(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast<size_t>(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_); + if (result < static_cast<size_t>(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } private: - FILE* fp_; - char *buffer_; - char *bufferEnd_; - char *current_; + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; }; //! Implement specialized version of PutN() with memset() for better performance. template<> inline void PutN(FileWriteStream& stream, char c, size_t n) { - stream.PutN(c, n); + stream.PutN(c, n); } -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/dtoa.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/dtoa.h index 8d6350e626..bf2e9b2e59 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/dtoa.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/dtoa.h @@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin } } -inline unsigned CountDecimalDigit32(uint32_t n) { +inline int CountDecimalDigit32(uint32_t n) { // Simple pure C++ implementation was faster than __builtin_clz version in this situation. if (n < 10) return 1; if (n < 100) return 2; @@ -63,7 +63,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff const DiyFp wp_w = Mp - W; uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); uint64_t p2 = Mp.f & (one.f - 1); - unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] *len = 0; while (kappa > 0) { @@ -102,8 +102,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff kappa--; if (p2 < delta) { *K += kappa; - int index = -static_cast<int>(kappa); - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0)); + int index = -kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); return; } } diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/ieee754.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/ieee754.h index 82bb0b99e5..c2684ba2a3 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/ieee754.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/ieee754.h @@ -48,13 +48,13 @@ class Double { int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } - static unsigned EffectiveSignificandSize(int order) { + static int EffectiveSignificandSize(int order) { if (order >= -1021) return 53; else if (order <= -1074) return 0; else - return static_cast<unsigned>(order) + 1074; + return order + 1074; } private: diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/pow10.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/pow10.h index bf3a9afb04..02f475d705 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/pow10.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/pow10.h @@ -1,54 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_POW10_ #define RAPIDJSON_POW10_ -namespace rapidjson { +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN namespace internal { //! Computes integer powers of 10 in double (10.0^n). /*! This function uses lookup table for fast and accurate results. - \param n positive/negative exponent. Must <= 308. - \return 10.0^n + \param n non-negative exponent. Must <= 308. + \return 10.0^n */ inline double Pow10(int n) { - static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes - 1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300, - 1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280, - 1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260, - 1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240, - 1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220, - 1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200, - 1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180, - 1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160, - 1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140, - 1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120, - 1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100, - 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80, - 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, - 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, - 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, - 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0, - 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, - 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, - 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, - 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, - 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, - 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, - 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, - 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, - 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, - 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, - 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, - 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, - 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, - 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, - 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, - 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 - }; - RAPIDJSON_ASSERT(n <= 308); - return n < -308 ? 0.0 : e[n + 308]; + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; } } // namespace internal -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_POW10_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/regex.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/regex.h index 422a5240bf..e1a2faae5f 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/regex.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/regex.h @@ -29,6 +29,9 @@ RAPIDJSON_DIAG_OFF(implicit-fallthrough) #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) +#if __GNUC__ >= 7 +RAPIDJSON_DIAG_OFF(implicit-fallthrough) +#endif #endif #ifdef _MSC_VER @@ -43,12 +46,40 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_NAMESPACE_BEGIN namespace internal { +/////////////////////////////////////////////////////////////////////////////// +// DecodedStream + +template <typename SourceStream, typename Encoding> +class DecodedStream { +public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + +private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; +}; + /////////////////////////////////////////////////////////////////////////////// // GenericRegex static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 static const SizeType kRegexInvalidRange = ~SizeType(0); +template <typename Encoding, typename Allocator> +class GenericRegexSearch; + //! Regular expression engine with subset of ECMAscript grammar. /*! Supported regular expression syntax: @@ -84,45 +115,25 @@ static const SizeType kRegexInvalidRange = ~SizeType(0); template <typename Encoding, typename Allocator = CrtAllocator> class GenericRegex { public: + typedef Encoding EncodingType; typedef typename Encoding::Ch Ch; + template <typename, typename> friend class GenericRegexSearch; GenericRegex(const Ch* source, Allocator* allocator = 0) : states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), - stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_() + anchorBegin_(), anchorEnd_() { GenericStringStream<Encoding> ss(source); - DecodedStream<GenericStringStream<Encoding> > ds(ss); + DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss); Parse(ds); } - ~GenericRegex() { - Allocator::Free(stateSet_); - } + ~GenericRegex() {} bool IsValid() const { return root_ != kRegexInvalidState; } - template <typename InputStream> - bool Match(InputStream& is) const { - return SearchWithAnchoring(is, true, true); - } - - bool Match(const Ch* s) const { - GenericStringStream<Encoding> is(s); - return Match(is); - } - - template <typename InputStream> - bool Search(InputStream& is) const { - return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); - } - - bool Search(const Ch* s) const { - GenericStringStream<Encoding> is(s); - return Search(is); - } - private: enum Operator { kZeroOrOne, @@ -157,28 +168,6 @@ class GenericRegex { SizeType minIndex; }; - template <typename SourceStream> - class DecodedStream { - public: - DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } - unsigned Peek() { return codepoint_; } - unsigned Take() { - unsigned c = codepoint_; - if (c) // No further decoding when '\0' - Decode(); - return c; - } - - private: - void Decode() { - if (!Encoding::Decode(ss_, &codepoint_)) - codepoint_ = 0; - } - - SourceStream& ss_; - unsigned codepoint_; - }; - State& GetState(SizeType index) { RAPIDJSON_ASSERT(index < stateCount_); return states_.template Bottom<State>()[index]; @@ -200,7 +189,7 @@ class GenericRegex { } template <typename InputStream> - void Parse(DecodedStream<InputStream>& ds) { + void Parse(DecodedStream<InputStream, Encoding>& ds) { Allocator allocator; Stack<Allocator> operandStack(&allocator, 256); // Frag Stack<Allocator> operatorStack(&allocator, 256); // Operator @@ -327,14 +316,6 @@ class GenericRegex { printf("\n"); #endif } - - // Preallocate buffer for SearchWithAnchoring() - RAPIDJSON_ASSERT(stateSet_ == 0); - if (stateCount_ > 0) { - stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize())); - state0_.template Reserve<SizeType>(stateCount_); - state1_.template Reserve<SizeType>(stateCount_); - } } SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { @@ -483,7 +464,7 @@ class GenericRegex { } template <typename InputStream> - bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) { + bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) { unsigned r = 0; if (ds.Peek() < '0' || ds.Peek() > '9') return false; @@ -497,7 +478,7 @@ class GenericRegex { } template <typename InputStream> - bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) { + bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) { bool isBegin = true; bool negate = false; int step = 0; @@ -575,7 +556,7 @@ class GenericRegex { } template <typename InputStream> - bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) { + bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) { unsigned codepoint; switch (codepoint = ds.Take()) { case '^': @@ -603,34 +584,93 @@ class GenericRegex { } } + Stack<Allocator> states_; + Stack<Allocator> ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + bool anchorBegin_; + bool anchorEnd_; +}; + +template <typename RegexType, typename Allocator = CrtAllocator> +class GenericRegexSearch { +public: + typedef typename RegexType::EncodingType Encoding; + typedef typename Encoding::Ch Ch; + + GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : + regex_(regex), allocator_(allocator), ownAllocator_(0), + state0_(allocator, 0), state1_(allocator, 0), stateSet_() + { + RAPIDJSON_ASSERT(regex_.IsValid()); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize())); + state0_.template Reserve<SizeType>(regex_.stateCount_); + state1_.template Reserve<SizeType>(regex_.stateCount_); + } + + ~GenericRegexSearch() { + Allocator::Free(stateSet_); + RAPIDJSON_DELETE(ownAllocator_); + } + + template <typename InputStream> + bool Match(InputStream& is) { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) { + GenericStringStream<Encoding> is(s); + return Match(is); + } + + template <typename InputStream> + bool Search(InputStream& is) { + return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); + } + + bool Search(const Ch* s) { + GenericStringStream<Encoding> is(s); + return Search(is); + } + +private: + typedef typename RegexType::State State; + typedef typename RegexType::Range Range; + template <typename InputStream> - bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { - RAPIDJSON_ASSERT(IsValid()); - DecodedStream<InputStream> ds(is); + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { + DecodedStream<InputStream, Encoding> ds(is); state0_.Clear(); Stack<Allocator> *current = &state0_, *next = &state1_; const size_t stateSetSize = GetStateSetSize(); std::memset(stateSet_, 0, stateSetSize); - bool matched = AddState(*current, root_); + bool matched = AddState(*current, regex_.root_); unsigned codepoint; while (!current->Empty() && (codepoint = ds.Take()) != 0) { std::memset(stateSet_, 0, stateSetSize); next->Clear(); matched = false; for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) { - const State& sr = GetState(*s); + const State& sr = regex_.GetState(*s); if (sr.codepoint == codepoint || - sr.codepoint == kAnyCharacterClass || - (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + sr.codepoint == RegexType::kAnyCharacterClass || + (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) { matched = AddState(*next, sr.out) || matched; if (!anchorEnd && matched) return true; } if (!anchorBegin) - AddState(*next, root_); + AddState(*next, regex_.root_); } internal::Swap(current, next); } @@ -639,53 +679,46 @@ class GenericRegex { } size_t GetStateSetSize() const { - return (stateCount_ + 31) / 32 * 4; + return (regex_.stateCount_ + 31) / 32 * 4; } // Return whether the added states is a match state - bool AddState(Stack<Allocator>& l, SizeType index) const { + bool AddState(Stack<Allocator>& l, SizeType index) { RAPIDJSON_ASSERT(index != kRegexInvalidState); - const State& s = GetState(index); + const State& s = regex_.GetState(index); if (s.out1 != kRegexInvalidState) { // Split bool matched = AddState(l, s.out); return AddState(l, s.out1) || matched; } - else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) { - stateSet_[index >> 5] |= (1 << (index & 31)); + else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) { + stateSet_[index >> 5] |= (1u << (index & 31)); *l.template PushUnsafe<SizeType>() = index; } return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. } bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { - bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0; + bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0; while (rangeIndex != kRegexInvalidRange) { - const Range& r = GetRange(rangeIndex); - if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end) + const Range& r = regex_.GetRange(rangeIndex); + if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end) return yes; rangeIndex = r.next; } return !yes; } - Stack<Allocator> states_; - Stack<Allocator> ranges_; - SizeType root_; - SizeType stateCount_; - SizeType rangeCount_; - - static const unsigned kInfinityQuantifier = ~0u; - - // For SearchWithAnchoring() - uint32_t* stateSet_; // allocated by states_.GetAllocator() - mutable Stack<Allocator> state0_; - mutable Stack<Allocator> state1_; - bool anchorBegin_; - bool anchorEnd_; + const RegexType& regex_; + Allocator* allocator_; + Allocator* ownAllocator_; + Stack<Allocator> state0_; + Stack<Allocator> state1_; + uint32_t* stateSet_; }; typedef GenericRegex<UTF8<> > Regex; +typedef GenericRegexSearch<Regex> RegexSearch; } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/stack.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/stack.h index d4b4b6449d..5c5398c35c 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/stack.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/stack.h @@ -1,7 +1,29 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_ -namespace rapidjson { +#include "../allocators.h" +#include "swap.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN namespace internal { /////////////////////////////////////////////////////////////////////////////// @@ -13,71 +35,197 @@ namespace internal { template <typename Allocator> class Stack { public: - Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { - RAPIDJSON_ASSERT(stack_capacity_ > 0); - if (!allocator_) - own_allocator_ = allocator_ = new Allocator(); - stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); - stack_end_ = stack_ + stack_capacity_; - } - - ~Stack() { - Allocator::Free(stack_); - delete own_allocator_; // Only delete if it is owned by the stack - } - - void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } - - template<typename T> - T* Push(size_t count = 1) { - // Expand the stack if needed - if (stack_top_ + sizeof(T) * count >= stack_end_) { - size_t new_capacity = stack_capacity_ * 2; - size_t size = GetSize(); - size_t new_size = GetSize() + sizeof(T) * count; - if (new_capacity < new_size) - new_capacity = new_size; - stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); - stack_capacity_ = new_capacity; - stack_top_ = stack_ + size; - stack_end_ = stack_ + stack_capacity_; - } - T* ret = (T*)stack_top_; - stack_top_ += sizeof(T) * count; - return ret; - } - - template<typename T> - T* Pop(size_t count) { - RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); - stack_top_ -= count * sizeof(T); - return (T*)stack_top_; - } - - template<typename T> - T* Top() { - RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); - return (T*)(stack_top_ - sizeof(T)); - } - - template<typename T> - T* Bottom() { return (T*)stack_; } - - Allocator& GetAllocator() { return *allocator_; } - bool Empty() const { return stack_top_ == stack_; } - size_t GetSize() const { return stack_top_ - stack_; } - size_t GetCapacity() const { return stack_capacity_; } + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template<typename T> + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) + Expand<T>(count); + } + + template<typename T> + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve<T>(count); + return PushUnsafe<T>(count); + } + + template<typename T> + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_); + RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); + T* ret = reinterpret_cast<T*>(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template<typename T> + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast<T*>(stackTop_); + } + + template<typename T> + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + T* End() { return reinterpret_cast<T*>(stackTop_); } + + template<typename T> + const T* End() const { return reinterpret_cast<T*>(stackTop_); } + + template<typename T> + T* Bottom() { return reinterpret_cast<T*>(stack_); } + + template<typename T> + const T* Bottom() const { return reinterpret_cast<T*>(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } private: - Allocator* allocator_; - Allocator* own_allocator_; - char *stack_; - char *stack_top_; - char *stack_end_; - size_t stack_capacity_; + template<typename T> + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; }; } // namespace internal -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_STACK_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/strfunc.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/strfunc.h index bbf444fe6d..226439a767 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/strfunc.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/strfunc.h @@ -1,24 +1,69 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ #define RAPIDJSON_INTERNAL_STRFUNC_H_ -namespace rapidjson { +#include "../stream.h" +#include <cwchar> + +RAPIDJSON_NAMESPACE_BEGIN namespace internal { //! Custom strlen() which works on different character types. -/*! \tparam Ch Character type (e.g. char, wchar_t, short) - \param s Null-terminated input string. - \return Number of characters in the string. - \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. */ template <typename Ch> inline SizeType StrLen(const Ch* s) { - const Ch* p = s; - while (*p != '\0') - ++p; - return SizeType(p - s); + RAPIDJSON_ASSERT(s != 0); + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +template <> +inline SizeType StrLen(const char* s) { + return SizeType(std::strlen(s)); +} + +template <> +inline SizeType StrLen(const wchar_t* s) { + return SizeType(std::wcslen(s)); +} + +//! Returns number of code points in a encoded string. +template<typename Encoding> +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + RAPIDJSON_ASSERT(s != 0); + RAPIDJSON_ASSERT(outCount != 0); + GenericStringStream<Encoding> is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; } } // namespace internal -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/internal/strtod.h b/Source/ThirdParty/rapidjson/include/rapidjson/internal/strtod.h index 289c413b07..adf49e3496 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/internal/strtod.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/internal/strtod.h @@ -140,8 +140,8 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit significand++; size_t remaining = length - i; - const unsigned kUlpShift = 3; - const unsigned kUlp = 1 << kUlpShift; + const int kUlpShift = 3; + const int kUlp = 1 << kUlpShift; int64_t error = (remaining == 0) ? 0 : kUlp / 2; DiyFp v(significand, 0); @@ -177,17 +177,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit v = v.Normalize(); error <<= oldExp - v.e; - const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); - unsigned precisionSize = 64 - effectiveSignificandSize; + const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + int precisionSize = 64 - effectiveSignificandSize; if (precisionSize + kUlpShift >= 64) { - unsigned scaleExp = (precisionSize + kUlpShift) - 63; + int scaleExp = (precisionSize + kUlpShift) - 63; v.f >>= scaleExp; v.e += scaleExp; - error = (error >> scaleExp) + 1 + static_cast<int>(kUlp); + error = (error >> scaleExp) + 1 + kUlp; precisionSize -= scaleExp; } - DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize)); + DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; if (precisionBits >= halfWay + static_cast<unsigned>(error)) { diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/istreamwrapper.h b/Source/ThirdParty/rapidjson/include/rapidjson/istreamwrapper.h index f5fe28977e..8639c8c3c8 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/istreamwrapper.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/istreamwrapper.h @@ -54,7 +54,7 @@ class BasicIStreamWrapper { Ch Peek() const { typename StreamType::int_type c = stream_.peek(); - return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0'; + return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : static_cast<Ch>('\0'); } Ch Take() { diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/pointer.h b/Source/ThirdParty/rapidjson/include/rapidjson/pointer.h index 0206ac1c8b..0f377efecc 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/pointer.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/pointer.h @@ -240,7 +240,7 @@ class GenericPointer { template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer)) Append(T* name, Allocator* allocator = 0) const { - return Append(name, StrLen(name), allocator); + return Append(name, internal::StrLen(name), allocator); } #if RAPIDJSON_HAS_STDSTRING @@ -274,7 +274,7 @@ class GenericPointer { else { Ch name[21]; for (size_t i = 0; i <= length; i++) - name[i] = buffer[i]; + name[i] = static_cast<Ch>(buffer[i]); Token token = { name, length, index }; return Append(token, allocator); } @@ -758,7 +758,7 @@ class GenericPointer { */ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { if (!allocator_) // allocator is independently owned. - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) @@ -806,7 +806,7 @@ class GenericPointer { // Create own allocator if user did not supply. if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); // Count number of '/' as tokenCount tokenCount_ = 0; @@ -1029,8 +1029,8 @@ class GenericPointer { unsigned char u = static_cast<unsigned char>(c); static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; os_.Put('%'); - os_.Put(hexDigits[u >> 4]); - os_.Put(hexDigits[u & 15]); + os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4])); + os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15])); } private: OutputStream& os_; diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/prettywriter.h b/Source/ThirdParty/rapidjson/include/rapidjson/prettywriter.h index 1167631063..2a72c255d7 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/prettywriter.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/prettywriter.h @@ -1,163 +1,280 @@ -#ifndef RAPIDJSON_PRETTYWRITER_H_ -#define RAPIDJSON_PRETTYWRITER_H_ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. // Modified by Ali Kamarainen for Urho3D +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + #include "writer.h" -namespace rapidjson { +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; //! Writer with indentation and spacing. /*! - \tparam OutputStream Type of ouptut os. - \tparam Encoding Encoding of both source strings and output. - \tparam Allocator Type of allocator for allocating memory of stack. + \tparam OutputStream Type of ouptut os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. */ -template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> > -class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, Allocator> { +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { public: - typedef Writer<OutputStream, SourceEncoding, TargetEncoding, Allocator> Base; - typedef typename Base::Ch Ch; - - //! Constructor - /*! \param os Output os. - \param allocator User supplied allocator. If it is null, it will create a private one. - \param levelDepth Initial capacity of - */ - PrettyWriter(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : - Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} - - //! Set custom indentation. - /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r'). - \param indentCharCount Number of indent characters for each indentation level. - \note The default indentation is 4 spaces. - */ - PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { - // Urho3D: in order to be consistent witht the XMLFile API, allow any character. - // RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); - indentChar_ = indentChar; - indentCharCount_ = indentCharCount; - return *this; - } - - //@name Implementation of Handler. - //@{ - - PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } - PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; } - PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; } - PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; } - PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } - PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } - PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } - - PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) { - (void)copy; - PrettyPrefix(kStringType); - Base::WriteString(str, length); - return *this; - } - - PrettyWriter& StartObject() { - PrettyPrefix(kObjectType); - new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); - Base::WriteStartObject(); - return *this; - } - - PrettyWriter& EndObject(SizeType memberCount = 0) { - (void)memberCount; - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); - bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; - - if (!empty) { - Base::os_.Put('\n'); - WriteIndent(); - } - Base::WriteEndObject(); - if (Base::level_stack_.Empty()) // end of json text - Base::os_.Flush(); - return *this; - } - - PrettyWriter& StartArray() { - PrettyPrefix(kArrayType); - new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); - Base::WriteStartArray(); - return *this; - } - - PrettyWriter& EndArray(SizeType memberCount = 0) { - (void)memberCount; - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); - bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; - - if (!empty) { - Base::os_.Put('\n'); - WriteIndent(); - } - Base::WriteEndArray(); - if (Base::level_stack_.Empty()) // end of json text - Base::os_.Flush(); - return *this; - } - - //@} - - //! Simpler but slower overload. - PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); } + typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + PrettyWriter(PrettyWriter&& rhs) : + Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} +#endif + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + // Urho3D: in order to be consistent with the XMLFile API, allow any character. + //RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kNumberType); + return Base::WriteString(str, length); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string<Ch>& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object + RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value + + bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndObject(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); + bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; + + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndArray(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + PrettyPrefix(type); + return Base::WriteRawValue(json, length); + } protected: - void PrettyPrefix(Type type) { - (void)type; - if (Base::level_stack_.GetSize() != 0) { // this value is not at root - typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>(); - - if (level->inArray) { - if (level->valueCount > 0) { - Base::os_.Put(','); // add comma if it is not the first element in array - Base::os_.Put('\n'); - } - else - Base::os_.Put('\n'); - WriteIndent(); - } - else { // in object - if (level->valueCount > 0) { - if (level->valueCount % 2 == 0) { - Base::os_.Put(','); - Base::os_.Put('\n'); - } - else { - Base::os_.Put(':'); - Base::os_.Put(' '); - } - } - else - Base::os_.Put('\n'); - - if (level->valueCount % 2 == 0) - WriteIndent(); - } - if (!level->inArray && level->valueCount % 2 == 0) - RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name - level->valueCount++; - } - else - RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); - } - - void WriteIndent() { - size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; - PutN(Base::os_, indentChar_, count); - } - - Ch indentChar_; - unsigned indentCharCount_; + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); + } + + if (!(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count); + } + + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); }; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/rapidjson.h b/Source/ThirdParty/rapidjson/include/rapidjson/rapidjson.h index 753396d163..57ab8514dd 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/rapidjson.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/rapidjson.h @@ -1,73 +1,360 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_RAPIDJSON_H_ #define RAPIDJSON_RAPIDJSON_H_ -// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) -// Version 0.1 +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overriden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include <cstdlib> // malloc(), realloc(), free(), size_t +#include <cstring> // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x -#include <cstdlib> // malloc(), realloc(), free() -#include <cstring> // memcpy() +// token concatenation +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include <string> +#endif // RAPIDJSON_HAS_STDSTRING /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NO_INT64DEFINE -// Here defines int64_t and uint64_t types in global namespace. -// If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this. +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ #ifndef RAPIDJSON_NO_INT64DEFINE -#ifdef _MSC_VER -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#define RAPIDJSON_FORCEINLINE __forceinline +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" #else +// Other compilers should have this. +#include <stdint.h> #include <inttypes.h> -#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE #endif #endif // RAPIDJSON_NO_INT64TYPEDEF +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_ENDIAN -#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine -#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine //! Endianness of the machine. -/*! GCC provided macro for detecting endianness of the target machine. But other - compilers may not have this. User can define RAPIDJSON_ENDIAN to either - RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp */ #ifndef RAPIDJSON_ENDIAN -#ifdef __BYTE_ORDER__ -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include <endian.h> +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && defined(_M_ARM) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 #else -#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN -#endif // __BYTE_ORDER__ +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. Currently the default uses 4 bytes + alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms. + User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#if RAPIDJSON_64BIT == 1 +#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u)) #else -#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise. +#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) #endif -#endif // RAPIDJSON_ENDIAN +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32)) +#endif /////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_ALIGNSIZE +// RAPIDJSON_48BITPOINTER_OPTIMIZATION -//! Data alignment of the machine. +//! Use only lower 48-bit address for some pointers. /*! - Some machine requires strict data alignment. - Currently the default uses 4 bytes alignment. User can customize this. + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. */ -#ifndef RAPIDJSON_ALIGN -#define RAPIDJSON_ALIGN(x) ((x + 3) & ~3) +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) #endif /////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2/Neon optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel + or ARM compatible processors. -// Enable SSE2 optimization. -//#define RAPIDJSON_SSE2 + To enable these optimizations, three different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 -// Enable SSE4.2 optimization. -//#define RAPIDJSON_SSE42 + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode -#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // Enable ARM Neon optimization. + #define RAPIDJSON_NEON + \endcode + + \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) #define RAPIDJSON_SIMD #endif @@ -75,20 +362,49 @@ typedef unsigned __int64 uint64_t; // RAPIDJSON_NO_SIZETYPEDEFINE #ifndef RAPIDJSON_NO_SIZETYPEDEFINE -namespace rapidjson { -//! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t. -/*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE. +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. */ typedef unsigned SizeType; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END #endif +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_ASSERT //! Assertion. -/*! By default, rapidjson uses C assert() for assertion. - User can override it by defining RAPIDJSON_ASSERT(x) macro. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. */ #ifndef RAPIDJSON_ASSERT #include <cassert> @@ -98,159 +414,215 @@ typedef unsigned SizeType; /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_STATIC_ASSERT -// Adopt from boost +// Prefer C++11 static_assert, if available +#ifndef RAPIDJSON_STATIC_ASSERT +#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) +#define RAPIDJSON_STATIC_ASSERT(x) \ + static_assert(x, RAPIDJSON_STRINGIFY(x)) +#endif // C++11 +#endif // RAPIDJSON_STATIC_ASSERT + +// Adopt C++03 implementation from boost #ifndef RAPIDJSON_STATIC_ASSERT -namespace rapidjson { +#ifndef __clang__ +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif +RAPIDJSON_NAMESPACE_BEGIN template <bool x> struct STATIC_ASSERTION_FAILURE; template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; -template<int x> struct StaticAssertTest {}; -} // namespace rapidjson +template <size_t x> struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END -#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) -#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) -#define RAPIDJSON_DO_JOIN2(X, Y) X##Y +#if defined(__GNUC__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +#ifndef __clang__ +//!@endcond +#endif -#define RAPIDJSON_STATIC_ASSERT(x) typedef ::rapidjson::StaticAssertTest<\ - sizeof(::rapidjson::STATIC_ASSERTION_FAILURE<bool(x) >)>\ - RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif // RAPIDJSON_STATIC_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif #endif /////////////////////////////////////////////////////////////////////////////// // Helpers +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + #define RAPIDJSON_MULTILINEMACRO_BEGIN do { #define RAPIDJSON_MULTILINEMACRO_END \ } while((void)0, 0) -/////////////////////////////////////////////////////////////////////////////// -// Allocators and Encodings - -#include "allocators.h" -#include "encodings.h" - -namespace rapidjson { +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) /////////////////////////////////////////////////////////////////////////////// -// Stream - -/*! \class rapidjson::Stream - \brief Concept for reading and writing characters. - - For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF - For write-only stream, only need to implement Put() and Flush(). +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif -\code -concept Stream { - typename Ch; //!< Character type of the stream. +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) - //! Read the current character from stream without moving the read cursor. - Ch Peek() const; +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) - //! Read the current character from stream and moving the read cursor to next character. - Ch Take(); +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif - //! Get the current read cursor. - //! \return Number of characters read from start. - size_t Tell(); +#elif defined(_MSC_VER) - //! Begin writing operation at the current read pointer. - //! \return The begin writer pointer. - Ch* PutBegin(); +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) - //! Write a character. - void Put(Ch c); +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) - //! Flush the buffer. - void Flush(); +#else - //! End the writing operation. - //! \param begin The begin write pointer returned by PutBegin(). - //! \return Number of characters written. - size_t PutEnd(Ch* begin); -} -\endcode -*/ +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ -//! Put N copies of a character to a stream. -template<typename Stream, typename Ch> -inline void PutN(Stream& stream, Ch c, size_t n) { - for (size_t i = 0; i < n; i++) - stream.Put(c); -} +#endif // RAPIDJSON_DIAG_* /////////////////////////////////////////////////////////////////////////////// -// StringStream +// C++11 features -//! Read-only string stream. -/*! \implements Stream -*/ -template <typename Encoding> -struct GenericStringStream { - typedef typename Encoding::Ch Ch; - - GenericStringStream(const Ch *src) : src_(src), head_(src) {} +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#if __has_feature(cxx_rvalue_references) && \ + (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) - Ch Peek() const { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() const { return src_ - head_; } +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif - const Ch* src_; //!< Current read position. - const Ch* head_; //!< Original head of the string. -}; +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR -typedef GenericStringStream<UTF8<> > StringStream; +//!@endcond /////////////////////////////////////////////////////////////////////////////// -// InsituStringStream - -//! A read-write string stream. -/*! This string stream is particularly designed for in-situ parsing. - \implements Stream -*/ -template <typename Encoding> -struct GenericInsituStringStream { - typedef typename Encoding::Ch Ch; - - GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} - - // Read - Ch Peek() { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() { return src_ - head_; } - - // Write - Ch* PutBegin() { return dst_ = src_; } - void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } - void Flush() {} - size_t PutEnd(Ch* begin) { return dst_ - begin; } - - Ch* src_; - Ch* dst_; - Ch* head_; -}; +// new/delete -typedef GenericInsituStringStream<UTF8<> > InsituStringStream; +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(TypeName) new TypeName +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif /////////////////////////////////////////////////////////////////////////////// // Type +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + //! Type of JSON value enum Type { - kNullType = 0, //!< null - kFalseType = 1, //!< false - kTrueType = 2, //!< true - kObjectType = 3, //!< object - kArrayType = 4, //!< array - kStringType = 5, //!< string - kNumberType = 6, //!< number + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number }; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/reader.h b/Source/ThirdParty/rapidjson/include/rapidjson/reader.h index 36f6d50c68..120c31115f 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/reader.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/reader.h @@ -1,68 +1,189 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_READER_H_ #define RAPIDJSON_READER_H_ -// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) -// Version 0.1 +/*! \file reader.h */ -#include "rapidjson.h" -#include "encodings.h" -#include "internal/pow10.h" +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" +#include "internal/meta.h" #include "internal/stack.h" -#include <csetjmp> +#include "internal/strtod.h" +#include <limits> +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif #ifdef RAPIDJSON_SSE42 #include <nmmintrin.h> #elif defined(RAPIDJSON_SSE2) #include <emmintrin.h> +#elif defined(RAPIDJSON_NEON) +#include <arm_neon.h> #endif #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4127) // conditional expression is constant +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END #endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include <stdexcept> // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ #ifndef RAPIDJSON_PARSE_ERROR -#define RAPIDJSON_PARSE_ERROR(msg, offset) \ - RAPIDJSON_MULTILINEMACRO_BEGIN \ - parseError_ = msg; \ - errorOffset_ = offset; \ - longjmp(jmpbuf_, 1); \ - RAPIDJSON_MULTILINEMACRO_END +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END #endif -namespace rapidjson { +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN /////////////////////////////////////////////////////////////////////////////// // ParseFlag +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + //! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ enum ParseFlag { - kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. - kParseInsituFlag = 1, //!< In-situ(destructive) parsing. - kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS }; /////////////////////////////////////////////////////////////////////////////// // Handler -/*! \class rapidjson::Handler - \brief Concept for receiving events from GenericReader upon parsing. +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. \code concept Handler { - typename Ch; - - void Null(); - void Bool(bool b); - void Int(int i); - void Uint(unsigned i); - void Int64(int64_t i); - void Uint64(uint64_t i); - void Double(double d); - void String(const Ch* str, SizeType length, bool copy); - void StartObject(); - void EndObject(SizeType memberCount); - void StartArray(); - void EndArray(SizeType elementCount); + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); }; \endcode */ @@ -71,599 +192,2030 @@ concept Handler { //! Default implementation of Handler. /*! This can be used as base class of any reader handler. - \implements Handler + \note implements Handler concept */ -template<typename Encoding = UTF8<> > +template<typename Encoding = UTF8<>, typename Derived = void> struct BaseReaderHandler { - typedef typename Encoding::Ch Ch; - - void Default() {} - void Null() { Default(); } - void Bool(bool) { Default(); } - void Int(int) { Default(); } - void Uint(unsigned) { Default(); } - void Int64(int64_t) { Default(); } - void Uint64(uint64_t) { Default(); } - void Double(double) { Default(); } - void String(const Ch*, SizeType, bool) { Default(); } - void StartObject() { Default(); } - void EndObject(SizeType) { Default(); } - void StartArray() { Default(); } - void EndArray(SizeType) { Default(); } + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast<Override&>(*this).Default(); } + bool Bool(bool) { return static_cast<Override&>(*this).Default(); } + bool Int(int) { return static_cast<Override&>(*this).Default(); } + bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); } + bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); } + bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); } + bool Double(double) { return static_cast<Override&>(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); } + bool StartObject() { return static_cast<Override&>(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); } + bool StartArray() { return static_cast<Override&>(*this).Default(); } + bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); } }; +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template<typename Stream, int = StreamTraits<Stream>::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template<typename Stream> +class StreamLocalCopy<Stream, 1> { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template<typename Stream> +class StreamLocalCopy<Stream, 0> { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + /////////////////////////////////////////////////////////////////////////////// // SkipWhitespace //! Skip the JSON white spaces in a stream. -/*! \param stream A input stream for skipping white spaces. - \note This function has SSE2/SSE4.2 specialization. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. */ template<typename InputStream> void SkipWhitespace(InputStream& is) { - InputStream s = is; // Use a local copy for optimization - while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') - s.Take(); - is = s; + internal::StreamLocalCopy<InputStream> copy(is); + InputStream& s(copy.s); + + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + s.Take(); +} + +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; } #ifdef RAPIDJSON_SSE42 //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { - static const char whitespace[16] = " \n\r\t"; - __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); - - for (;;) { - __m128i s = _mm_loadu_si128((const __m128i *)p); - unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); - if (r == 0) // all 16 characters are whitespace - p += 16; - else { // some of characters may be non-whitespace -#ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - if (_BitScanForward(&offset, r)) - return p + offset; -#else - if (r != 0) - return p + __builtin_ffs(r) - 1; -#endif - } - } + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } + + return SkipWhitespace(p, end); } #elif defined(RAPIDJSON_SSE2) //! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { - static const char whitespaces[4][17] = { - " ", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", - "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; - - __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); - __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); - __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); - __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); - - for (;;) { - __m128i s = _mm_loadu_si128((const __m128i *)p); - __m128i x = _mm_cmpeq_epi8(s, w0); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); - unsigned short r = ~_mm_movemask_epi8(x); - if (r == 0) // all 16 characters are whitespace - p += 16; - else { // some of characters may be non-whitespace -#ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - if (_BitScanForward(&offset, r)) - return p + offset; + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; #else - if (r != 0) - return p + __builtin_ffs(r) - 1; + return p + __builtin_ffs(r) - 1; #endif - } - } + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_NEON) + +//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract + + if (low == 0) { + if (high != 0) { + int lz =__builtin_clzll(high);; + return p + 8 + (lz >> 3); + } + } else { + int lz = __builtin_clzll(low);; + return p + (lz >> 3); + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (; p <= end - 16; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract + + if (low == 0) { + if (high != 0) { + int lz = __builtin_clzll(high); + return p + 8 + (lz >> 3); + } + } else { + int lz = __builtin_clzll(low); + return p + (lz >> 3); + } + } + + return SkipWhitespace(p, end); } -#endif // RAPIDJSON_SSE2 +#endif // RAPIDJSON_NEON #ifdef RAPIDJSON_SIMD //! Template function specialization for InsituStringStream -template<> inline void SkipWhitespace(InsituStringStream& is) { - is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_)); +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_)); } //! Template function specialization for StringStream template<> inline void SkipWhitespace(StringStream& is) { - is.src_ = SkipWhitespace_SIMD(is.src_); + is.src_ = SkipWhitespace_SIMD(is.src_); +} + +template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); } #endif // RAPIDJSON_SIMD /////////////////////////////////////////////////////////////////////////////// // GenericReader -//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. -/*! GenericReader parses JSON text from a stream, and send events synchronously to an +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an object implementing Handler concept. - It needs to allocate a stack for storing a single decoded string during + It needs to allocate a stack for storing a single decoded string during non-destructive parsing. - For in-situ parsing, the decoded string is directly written to the source + For in-situ parsing, the decoded string is directly written to the source text string, no temporary buffer is required. A GenericReader object can be reused for parsing multiple JSON text. - + \tparam SourceEncoding Encoding of the input stream. - \tparam TargetEncoding Encoding of the parse output. - \tparam Allocator Allocator type for stack. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. */ -template <typename SourceEncoding, typename TargetEncoding, typename Allocator = MemoryPoolAllocator<> > +template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator> class GenericReader { public: - typedef typename SourceEncoding::Ch Ch; - - //! Constructor. - /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) - \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) - */ - GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} - - //! Parse JSON text. - /*! \tparam parseFlags Combination of ParseFlag. - \tparam InputStream Type of input stream. - \tparam Handler Type of handler which must implement Handler concept. - \param stream Input stream to be parsed. - \param handler The handler to receive events. - \return Whether the parsing is successful. - */ - template <unsigned parseFlags, typename InputStream, typename Handler> - bool Parse(InputStream& is, Handler& handler) { - parseError_ = 0; - errorOffset_ = 0; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable -#endif - if (setjmp(jmpbuf_)) { -#ifdef _MSC_VER -#pragma warning(pop) -#endif - stack_.Clear(); - return false; - } - - SkipWhitespace(is); + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse<parseFlags>(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse<kParseDefaultFlags>(is, handler); + } + + //! Initialize JSON text token-by-token parsing + /*! + */ + void IterativeParseInit() { + parseResult_.Clear(); + state_ = IterativeParsingStartState; + } + + //! Parse one token from JSON text + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <unsigned parseFlags, typename InputStream, typename Handler> + bool IterativeParseNext(InputStream& is, Handler& handler) { + while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { + SkipWhitespaceAndComments<parseFlags>(is); + + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state_, t); + IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler); + + // If we've finished or hit an error... + if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) { + // Report errors. + if (d == IterativeParsingErrorState) { + HandleError(state_, is); + return false; + } + + // Transition to the finish state. + RAPIDJSON_ASSERT(d == IterativeParsingFinishState); + state_ = d; + + // If StopWhenDone is not set... + if (!(parseFlags & kParseStopWhenDoneFlag)) { + // ... and extra non-whitespace data is found... + SkipWhitespaceAndComments<parseFlags>(is); + if (is.Peek() != '\0') { + // ... this is considered an error. + HandleError(state_, is); + return false; + } + } + + // Success! We are done! + return true; + } + + // Transition to the new state. + state_ = d; + + // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now. + if (!IsIterativeParsingDelimiterState(n)) + return true; + } + + // We reached the end of file. + stack_.Clear(); + + if (state_ != IterativeParsingFinishState) { + HandleError(state_, is); + return false; + } + + return true; + } + + //! Check if token-by-token parsing JSON text is complete + /*! \return Whether the JSON has been fully decoded. + */ + RAPIDJSON_FORCEINLINE bool IterativeParseComplete() { + return IsIterativeParsingCompleteState(state_); + } - if (is.Peek() == '\0') - RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", is.Tell()); - else { - switch (is.Peek()) { - case '{': ParseObject<parseFlags>(is, handler); break; - case '[': ParseArray<parseFlags>(is, handler); break; - default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", is.Tell()); - } - SkipWhitespace(is); + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } - if (is.Peek() != '\0') - RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", is.Tell()); - } + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } - return true; - } + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } - bool HasParseError() const { return parseError_ != 0; } - const char* GetParseError() const { return parseError_; } - size_t GetErrorOffset() const { return errorOffset_; } +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } private: - // Parse object: { string : value, ... } - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseObject(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == '{'); - is.Take(); // Skip '{' - handler.StartObject(); - SkipWhitespace(is); - - if (is.Peek() == '}') { - is.Take(); - handler.EndObject(0); // empty object - return; - } - - for (SizeType memberCount = 0;;) { - if (is.Peek() != '"') - RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", is.Tell()); - - ParseString<parseFlags>(is, handler); - SkipWhitespace(is); - - if (is.Take() != ':') - RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", is.Tell()); - - SkipWhitespace(is); - - ParseValue<parseFlags>(is, handler); - SkipWhitespace(is); - - ++memberCount; - - switch(is.Take()) { - case ',': SkipWhitespace(is); break; - case '}': handler.EndObject(memberCount); return; - default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", is.Tell()); - } - } - } - - // Parse array: [ value, ... ] - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseArray(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == '['); - is.Take(); // Skip '[' - handler.StartArray(); - SkipWhitespace(is); - - if (is.Peek() == ']') { - is.Take(); - handler.EndArray(0); // empty array - return; - } - - for (SizeType elementCount = 0;;) { - ParseValue<parseFlags>(is, handler); - ++elementCount; - SkipWhitespace(is); - - switch (is.Take()) { - case ',': SkipWhitespace(is); break; - case ']': handler.EndArray(elementCount); return; - default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", is.Tell()); - } - } - } - - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseNull(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == 'n'); - is.Take(); - - if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') - handler.Null(); - else - RAPIDJSON_PARSE_ERROR("Invalid value", is.Tell() - 1); - } - - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseTrue(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == 't'); - is.Take(); - - if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') - handler.Bool(true); - else - RAPIDJSON_PARSE_ERROR("Invalid value", is.Tell()); - } - - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseFalse(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == 'f'); - is.Take(); - - if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') - handler.Bool(false); - else - RAPIDJSON_PARSE_ERROR("Invalid value", is.Tell() - 1); - } - - // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). - template<typename InputStream> - unsigned ParseHex4(InputStream& is) { - InputStream s = is; // Use a local copy for optimization - unsigned codepoint = 0; - for (int i = 0; i < 4; i++) { - Ch c = s.Take(); - codepoint <<= 4; - codepoint += c; - if (c >= '0' && c <= '9') - codepoint -= '0'; - else if (c >= 'A' && c <= 'F') - codepoint -= 'A' - 10; - else if (c >= 'a' && c <= 'f') - codepoint -= 'a' - 10; - else - RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1); - } - is = s; // Restore is - return codepoint; - } - - class StackStream { - public: - typedef typename TargetEncoding::Ch Ch; - - StackStream(internal::Stack<Allocator>& stack) : stack_(stack), length_(0) {} - void Put(Ch c) { - *stack_.template Push<Ch>() = c; - ++length_; - } - internal::Stack<Allocator>& stack_; - SizeType length_; - - private: - // Prohibit assignment for VC C4512 warning - StackStream& operator=(const StackStream&); - }; - - // Parse string and generate String event. Different code paths for kParseInsituFlag. - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseString(InputStream& is, Handler& handler) { - InputStream s = is; // Local copy for optimization - if (parseFlags & kParseInsituFlag) { - Ch *head = s.PutBegin(); - ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s); - size_t length = s.PutEnd(head) - 1; - RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false); - } - else { - StackStream stackStream(stack_); - ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream); - handler.String(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true); - } - is = s; // Restore is - } - - // Parse string to an output is - // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. - template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> - RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template<unsigned parseFlags, typename InputStream> + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n') {} + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString<parseFlags>(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + // Parse array: [ value, ... ] + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template<typename InputStream> + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template<typename InputStream> + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast<unsigned>(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } + + template <typename CharType> + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push<Ch>() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push<Ch>(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop<Ch>(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack<StackAllocator>& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy<InputStream> copy(is); + InputStream& s(copy.s); + + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream<typename TargetEncoding::Ch> stackStream(stack_); + ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast<SizeType>(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (RAPIDJSON_UNLIKELY(!success)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - static const char escape[256] = { - Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', - Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, - 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, - 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 - }; + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; #undef Z16 - - RAPIDJSON_ASSERT(is.Peek() == '\"'); - is.Take(); // Skip '\"' - - for (;;) { - Ch c = is.Peek(); - if (c == '\\') { // Escape - is.Take(); - Ch e = is.Take(); - if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) - os.Put(escape[(unsigned char)e]); - else if (e == 'u') { // Unicode - unsigned codepoint = ParseHex4(is); - if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { - // Handle UTF-16 surrogate pair - if (is.Take() != '\\' || is.Take() != 'u') - RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", is.Tell() - 2); - unsigned codepoint2 = ParseHex4(is); - if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) - RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", is.Tell() - 2); - codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; - } - TEncoding::Encode(os, codepoint); - } - else - RAPIDJSON_PARSE_ERROR("Unknown escape character", is.Tell() - 1); - } - else if (c == '"') { // Closing double quote - is.Take(); - os.Put('\0'); // null-terminate the string - return; - } - else if (c == '\0') - RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", is.Tell() - 1); - else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF - RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", is.Tell() - 1); - else { - if (parseFlags & kParseValidateEncodingFlag ? - !Transcoder<SEncoding, TEncoding>::Validate(is, os) : - !Transcoder<SEncoding, TEncoding>::Transcode(is, os)) - RAPIDJSON_PARSE_ERROR("Invalid encoding", is.Tell()); - } - } - } - - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseNumber(InputStream& is, Handler& handler) { - InputStream s = is; // Local copy for optimization - // Parse minus - bool minus = false; - if (s.Peek() == '-') { - minus = true; - s.Take(); - } - - // Parse int: zero / ( digit1-9 *DIGIT ) - unsigned i; - bool try64bit = false; - if (s.Peek() == '0') { - i = 0; - s.Take(); - } - else if (s.Peek() >= '1' && s.Peek() <= '9') { - i = s.Take() - '0'; - - if (minus) - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i >= 214748364) { // 2^31 = 2147483648 - if (i != 214748364 || s.Peek() > '8') { - try64bit = true; - break; - } - } - i = i * 10 + (s.Take() - '0'); - } - else - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i >= 429496729) { // 2^32 - 1 = 4294967295 - if (i != 429496729 || s.Peek() > '5') { - try64bit = true; - break; - } - } - i = i * 10 + (s.Take() - '0'); - } - } - else - RAPIDJSON_PARSE_ERROR("Expect a value here.", is.Tell()); - - // Parse 64bit int - uint64_t i64 = 0; - bool useDouble = false; - if (try64bit) { - i64 = i; - if (minus) - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808 - if (i64 != 922337203685477580uLL || s.Peek() > '8') { - useDouble = true; - break; - } - i64 = i64 * 10 + (s.Take() - '0'); - } - else - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615 - if (i64 != 1844674407370955161uLL || s.Peek() > '5') { - useDouble = true; - break; - } - i64 = i64 * 10 + (s.Take() - '0'); - } - } - - // Force double for big integer - double d = 0.0; - if (useDouble) { - d = (double)i64; - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (d >= 1E307) - RAPIDJSON_PARSE_ERROR("Number too big to store in double", is.Tell()); - d = d * 10 + (s.Take() - '0'); - } - } - - // Parse frac = decimal-point 1*DIGIT - int expFrac = 0; - if (s.Peek() == '.') { - if (!useDouble) { - d = try64bit ? (double)i64 : (double)i; - useDouble = true; - } - s.Take(); - - if (s.Peek() >= '0' && s.Peek() <= '9') { - d = d * 10 + (s.Take() - '0'); - --expFrac; - } - else - RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", is.Tell()); - - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (expFrac > -16) { - d = d * 10 + (s.Peek() - '0'); - --expFrac; - } - s.Take(); - } - } - - // Parse exp = e [ minus / plus ] 1*DIGIT - int exp = 0; - if (s.Peek() == 'e' || s.Peek() == 'E') { - if (!useDouble) { - d = try64bit ? (double)i64 : (double)i; - useDouble = true; - } - s.Take(); - - bool expMinus = false; - if (s.Peek() == '+') - s.Take(); - else if (s.Peek() == '-') { - s.Take(); - expMinus = true; - } - - if (s.Peek() >= '0' && s.Peek() <= '9') { - exp = s.Take() - '0'; - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); - if (exp > 308) - RAPIDJSON_PARSE_ERROR("Number too big to store in double", is.Tell()); - } - } - else - RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell()); - - if (expMinus) - exp = -exp; - } - - // Finish parsing, call event according to the type of number. - if (useDouble) { - d *= internal::Pow10(exp + expFrac); - handler.Double(minus ? -d : d); - } - else { - if (try64bit) { - if (minus) - handler.Int64(-(int64_t)i64); - else - handler.Uint64(i64); - } - else { - if (minus) - handler.Int(-(int)i); - else - handler.Uint(i); - } - } - - is = s; // restore is - } - - // Parse any JSON value - template<unsigned parseFlags, typename InputStream, typename Handler> - void ParseValue(InputStream& is, Handler& handler) { - switch (is.Peek()) { - case 'n': ParseNull <parseFlags>(is, handler); break; - case 't': ParseTrue <parseFlags>(is, handler); break; - case 'f': ParseFalse <parseFlags>(is, handler); break; - case '"': ParseString<parseFlags>(is, handler); break; - case '{': ParseObject<parseFlags>(is, handler); break; - case '[': ParseArray <parseFlags>(is, handler); break; - default : ParseNumber<parseFlags>(is, handler); - } - } - - static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. - internal::Stack<Allocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. - jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls. - const char* parseError_; - size_t errorOffset_; +//!@endcond + + for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) { + is.Take(); + os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)])); + } + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) { + // Handle UTF-16 surrogate pair + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder<SEncoding, TEncoding>::Validate(is, os) : + !Transcoder<SEncoding, TEncoding>::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template<typename InputStream, typename OutputStream> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream<char> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast<SizeType>(__builtin_ffs(r) - 1); + #endif + if (length != 0) { + char* q = reinterpret_cast<char*>(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast<size_t>(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast<size_t>(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#elif defined(RAPIDJSON_NEON) + // StringStream -> StackStream<char> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + unsigned lz = (unsigned)__builtin_clzll(high);; + length = 8 + (lz >> 3); + escaped = true; + } + } else { + unsigned lz = (unsigned)__builtin_clzll(low);; + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + if (length != 0) { + char* q = reinterpret_cast<char*>(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16, q += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + unsigned lz = (unsigned)__builtin_clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + unsigned lz = (unsigned)__builtin_clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + for (const char* pend = p + length; p != pend; ) { + *q++ = *p++; + } + break; + } + vst1q_u8(reinterpret_cast<uint8_t *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract + + if (low == 0) { + if (high != 0) { + int lz = __builtin_clzll(high); + p += 8 + (lz >> 3); + break; + } + } else { + int lz = __builtin_clzll(low); + p += lz >> 3; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif // RAPIDJSON_NEON + + template<typename InputStream, bool backup, bool pushOnTake> + class NumberStream; + + template<typename InputStream> + class NumberStream<InputStream, false, false> { + public: + typedef typename InputStream::Ch Ch; + + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template<typename InputStream> + class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> { + typedef NumberStream<InputStream, false, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast<char>(Base::is.Peek())); + return Base::is.Take(); + } + + RAPIDJSON_FORCEINLINE void Push(char c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream<char> stackStream; + }; + + template<typename InputStream> + class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> { + typedef NumberStream<InputStream, true, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy<InputStream> copy(is); + NumberStream<InputStream, + ((parseFlags & kParseNumbersAsStringsFlag) != 0) ? + ((parseFlags & kParseInsituFlag) == 0) : + ((parseFlags & kParseFullPrecisionFlag) != 0), + (parseFlags & kParseNumbersAsStringsFlag) != 0 && + (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; + + // Parse minus + bool minus = Consume(s, '-'); + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { + i = 0; + s.TakePush(); + } + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { + i = static_cast<unsigned>(s.TakePush() - '0'); + + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + if (Consume(s, 'N')) { + if (Consume(s, 'a') && Consume(s, 'N')) { + d = std::numeric_limits<double>::quiet_NaN(); + useNanOrInf = true; + } + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { + if (Consume(s, 'n') && Consume(s, 'f')) { + d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity()); + useNanOrInf = true; + + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + } + + if (RAPIDJSON_UNLIKELY(!useNanOrInf)) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + if (use64bit) { + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast<double>(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast<double>(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (Consume(s, '.')) { + decimalPosition = s.Length(); + + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast<double>(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast<double>(use64bit ? i64 : i); +#endif + useDouble = true; + } + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (RAPIDJSON_LIKELY(d > 0.0)) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (Consume(s, 'e') || Consume(s, 'E')) { + if (!useDouble) { + d = static_cast<double>(use64bit ? i64 : i); + useDouble = true; + } + + bool expMinus = false; + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) + expMinus = true; + + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast<int>(s.Take() - '0'); + if (expMinus) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast<int>(s.Take() - '0'); + if (exp >= 214748364) { // Issue #313: prevent overflow exponent + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast<int>(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast<SizeType>(s.Length()); + StringStream srcStream(s.Pop()); + StackStream<typename TargetEncoding::Ch> dstStream(stack_); + while (numCharsToCopy--) { + Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else { + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast<int64_t>(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast<int32_t>(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull <parseFlags>(is, handler); break; + case 't': ParseTrue <parseFlags>(is, handler); break; + case 'f': ParseFalse <parseFlags>(is, handler); break; + case '"': ParseString<parseFlags>(is, handler); break; + case '{': ParseObject<parseFlags>(is, handler); break; + case '[': ParseArray <parseFlags>(is, handler); break; + default : + ParseNumber<parseFlags>(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingFinishState = 0, // sink states at top + IterativeParsingErrorState, // sink states at top + IterativeParsingStartState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingMemberValueState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + // Delimiter states (at bottom) + IterativeParsingElementDelimiterState, + IterativeParsingMemberDelimiterState, + IterativeParsingKeyValueDelimiterState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) + return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]); + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + }; // End of G + + return static_cast<IterativeParsingState>(G[state][token]); + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template <unsigned parseFlags, typename InputStream, typename Handler> + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push<SizeType>(1) = n; + // Initialize and push the member/element count. + *stack_.template Push<SizeType>(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString<parseFlags>(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop<SizeType>(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop<SizeType>(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template <typename InputStream> + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) { + return s >= IterativeParsingElementDelimiterState; + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) { + return s <= IterativeParsingErrorState; + } + + template <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; + IterativeParsingState state_; }; // class GenericReader //! Reader with UTF8 encoding and default allocator. typedef GenericReader<UTF8<>, UTF8<> > Reader; -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif #ifdef _MSC_VER -#pragma warning(pop) +RAPIDJSON_DIAG_POP #endif #endif // RAPIDJSON_READER_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/schema.h b/Source/ThirdParty/rapidjson/include/rapidjson/schema.h index b182aa27f0..348dd379c3 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/schema.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/schema.h @@ -349,6 +349,7 @@ class Schema { Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : allocator_(allocator), + typeless_(schemaDocument->GetTypeless()), enum_(), enumCount_(), not_(), @@ -453,7 +454,7 @@ class Schema { for (SizeType i = 0; i < propertyCount_; i++) { new (&properties_[i]) Property(); properties_[i].name = allProperties[i]; - properties_[i].schema = GetTypeless(); + properties_[i].schema = typeless_; } } } @@ -575,9 +576,7 @@ class Schema { } ~Schema() { - if (allocator_) { - allocator_->Free(enum_); - } + AllocatorType::Free(enum_); if (properties_) { for (SizeType i = 0; i < propertyCount_; i++) properties_[i].~Property(); @@ -592,7 +591,7 @@ class Schema { #if RAPIDJSON_SCHEMA_HAS_REGEX if (pattern_) { pattern_->~RegexType(); - allocator_->Free(pattern_); + AllocatorType::Free(pattern_); } #endif } @@ -610,12 +609,12 @@ class Schema { else if (additionalItemsSchema_) context.valueSchema = additionalItemsSchema_; else if (additionalItems_) - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; else RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); } else - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; context.arrayElementIndex++; } @@ -792,7 +791,7 @@ class Schema { if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { if (context.patternPropertiesSchemaCount > 0) { context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; } else @@ -807,7 +806,7 @@ class Schema { if (additionalPropertiesSchema_) { if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; } else @@ -815,7 +814,7 @@ class Schema { return true; } else if (additionalProperties_) { - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; return true; } @@ -881,7 +880,7 @@ class Schema { #define RAPIDJSON_STRING_(name, ...) \ static const ValueType& Get##name##String() {\ static const Ch s[] = { __VA_ARGS__, '\0' };\ - static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\ + static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\ return v;\ } @@ -949,11 +948,6 @@ class Schema { SizeType count; }; - static const SchemaType* GetTypeless() { - static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); - return &typeless; - } - template <typename V1, typename V2> void AddUniqueElement(V1& a, const V2& v) { for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) @@ -1011,7 +1005,8 @@ class Schema { } static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { - return pattern->Search(str); + GenericRegexSearch<RegexType> rs(*pattern); + return rs.Search(str); } #elif RAPIDJSON_SCHEMA_USE_STDREGEX template <typename ValueType> @@ -1117,8 +1112,8 @@ class Schema { if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); } - else if (maximum_.IsUint64()) - /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64() + else if (maximum_.IsUint64()) { } + /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() else if (!CheckDoubleMaximum(context, static_cast<double>(i))) return false; } @@ -1218,6 +1213,7 @@ class Schema { }; AllocatorType* allocator_; + const SchemaType* typeless_; uint64_t* enum_; SizeType enumCount_; SchemaArray allOf_; @@ -1267,7 +1263,7 @@ struct TokenHelper { char buffer[21]; size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); for (size_t i = 0; i < length; i++) - *documentStack.template Push<Ch>() = buffer[i]; + *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]); } }; @@ -1343,11 +1339,15 @@ class GenericSchemaDocument { allocator_(allocator), ownAllocator_(), root_(), + typeless_(), schemaMap_(allocator, kInitialSchemaMapSize), schemaRef_(allocator, kInitialSchemaRefSize) { if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); // Generate root schema, it will call CreateSchema() to create sub-schemas, // And call AddRefSchema() if there are $ref. @@ -1365,6 +1365,9 @@ class GenericSchemaDocument { new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_); } } + else if (refEntry->schema) + *refEntry->schema = typeless_; + refEntry->~SchemaRefEntry(); } @@ -1380,12 +1383,14 @@ class GenericSchemaDocument { allocator_(rhs.allocator_), ownAllocator_(rhs.ownAllocator_), root_(rhs.root_), + typeless_(rhs.typeless_), schemaMap_(std::move(rhs.schemaMap_)), schemaRef_(std::move(rhs.schemaRef_)) { rhs.remoteProvider_ = 0; rhs.allocator_ = 0; rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; } #endif @@ -1394,6 +1399,11 @@ class GenericSchemaDocument { while (!schemaMap_.Empty()) schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry(); + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } + RAPIDJSON_DELETE(ownAllocator_); } @@ -1428,7 +1438,7 @@ class GenericSchemaDocument { void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { if (schema) - *schema = SchemaType::GetTypeless(); + *schema = typeless_; if (v.GetType() == kObjectType) { const SchemaType* s = GetSchema(pointer); @@ -1473,7 +1483,7 @@ class GenericSchemaDocument { if (i > 0) { // Remote reference, resolve immediately if (remoteProvider_) { - if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) { PointerType pointer(&s[i], len - i, allocator_); if (pointer.IsValid()) { if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { @@ -1515,6 +1525,8 @@ class GenericSchemaDocument { return PointerType(); } + const SchemaType* GetTypeless() const { return typeless_; } + static const size_t kInitialSchemaMapSize = 64; static const size_t kInitialSchemaRefSize = 64; @@ -1522,6 +1534,7 @@ class GenericSchemaDocument { Allocator *allocator_; Allocator *ownAllocator_; const SchemaType* root_; //!< Root schema. + SchemaType* typeless_; internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref }; @@ -1575,11 +1588,11 @@ class GenericSchemaValidator : : schemaDocument_(&schemaDocument), root_(schemaDocument.GetRoot()), - outputHandler_(GetNullHandler()), stateAllocator_(allocator), ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), + outputHandler_(CreateNullHandler()), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(0) @@ -1603,11 +1616,12 @@ class GenericSchemaValidator : : schemaDocument_(&schemaDocument), root_(schemaDocument.GetRoot()), - outputHandler_(outputHandler), stateAllocator_(allocator), ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), + outputHandler_(outputHandler), + nullHandler_(0), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(0) @@ -1618,6 +1632,10 @@ class GenericSchemaValidator : //! Destructor. ~GenericSchemaValidator() { Reset(); + if (nullHandler_) { + nullHandler_->~OutputHandler(); + StateAllocator::Free(nullHandler_); + } RAPIDJSON_DELETE(ownStateAllocator_); } @@ -1771,7 +1789,7 @@ RAPIDJSON_MULTILINEMACRO_END } virtual void FreeState(void* p) { - return StateAllocator::Free(p); + StateAllocator::Free(p); } private: @@ -1791,11 +1809,11 @@ RAPIDJSON_MULTILINEMACRO_END : schemaDocument_(&schemaDocument), root_(root), - outputHandler_(GetNullHandler()), stateAllocator_(allocator), ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), + outputHandler_(CreateNullHandler()), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(depth) @@ -1805,7 +1823,7 @@ RAPIDJSON_MULTILINEMACRO_END StateAllocator& GetStateAllocator() { if (!stateAllocator_) - stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator()); + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); return *stateAllocator_; } @@ -1823,8 +1841,8 @@ RAPIDJSON_MULTILINEMACRO_END const SchemaType** sa = CurrentContext().patternPropertiesSchemas; typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; bool valueUniqueness = CurrentContext().valueUniqueness; - if (CurrentContext().valueSchema) - PushSchema(*CurrentContext().valueSchema); + RAPIDJSON_ASSERT(CurrentContext().valueSchema); + PushSchema(*CurrentContext().valueSchema); if (count > 0) { CurrentContext().objectPatternValidatorType = patternValidatorType; @@ -1909,20 +1927,20 @@ RAPIDJSON_MULTILINEMACRO_END Context& CurrentContext() { return *schemaStack_.template Top<Context>(); } const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); } - static OutputHandler& GetNullHandler() { - static OutputHandler nullHandler; - return nullHandler; + OutputHandler& CreateNullHandler() { + return *(nullHandler_ = new (GetStateAllocator().Malloc(sizeof(OutputHandler))) OutputHandler); } static const size_t kDefaultSchemaStackCapacity = 1024; static const size_t kDefaultDocumentStackCapacity = 256; const SchemaDocumentType* schemaDocument_; const SchemaType& root_; - OutputHandler& outputHandler_; StateAllocator* stateAllocator_; StateAllocator* ownStateAllocator_; internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch) + OutputHandler& outputHandler_; + OutputHandler* nullHandler_; bool valid_; #if RAPIDJSON_SCHEMA_VERBOSE unsigned depth_; diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/stringbuffer.h b/Source/ThirdParty/rapidjson/include/rapidjson/stringbuffer.h index 74415cbb83..4e38b82c3d 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/stringbuffer.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/stringbuffer.h @@ -1,50 +1,121 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_STRINGBUFFER_H_ #define RAPIDJSON_STRINGBUFFER_H_ -#include "rapidjson.h" +#include "stream.h" +#include "internal/stack.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include <utility> // std::move +#endif + #include "internal/stack.h" -namespace rapidjson { +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN //! Represents an in-memory output stream. /*! - \tparam Encoding Encoding of the stream. - \tparam Allocator type for allocating memory buffer. - \implements Stream + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept */ template <typename Encoding, typename Allocator = CrtAllocator> -struct GenericStringBuffer { - typedef typename Encoding::Ch Ch; +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif - GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + void Put(Ch c) { *stack_.template Push<Ch>() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; } + void Flush() {} - void Put(Ch c) { *stack_.template Push<Ch>() = c; } - void Flush() {} + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop<Ch>(1); + } - void Clear() { stack_.Clear(); } + void Reserve(size_t count) { stack_.template Reserve<Ch>(count); } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } - const Ch* GetString() const { - // Push and pop a null terminator. This is safe. - *stack_.template Push<Ch>() = '\0'; - stack_.template Pop<Ch>(1); + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.template Pop<Ch>(1); - return stack_.template Bottom<Ch>(); - } + return stack_.template Bottom<Ch>(); + } - size_t GetSize() const { return stack_.GetSize(); } + //! Get the size of string in bytes in the string buffer. + size_t GetSize() const { return stack_.GetSize(); } - static const size_t kDefaultCapacity = 256; - mutable internal::Stack<Allocator> stack_; + //! Get the length of string in Ch in the string buffer. + size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack<Allocator> stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); }; +//! String buffer with UTF8 encoding typedef GenericStringBuffer<UTF8<> > StringBuffer; +template<typename Encoding, typename Allocator> +inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { + stream.Reserve(count); +} + +template<typename Encoding, typename Allocator> +inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + //! Implement specialized version of PutN() with memset() for better performance. template<> inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { - memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); + std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); } -} // namespace rapidjson +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif #endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/Source/ThirdParty/rapidjson/include/rapidjson/writer.h b/Source/ThirdParty/rapidjson/include/rapidjson/writer.h index 56d5804344..61cd0707e0 100644 --- a/Source/ThirdParty/rapidjson/include/rapidjson/writer.h +++ b/Source/ThirdParty/rapidjson/include/rapidjson/writer.h @@ -1,249 +1,704 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + #ifndef RAPIDJSON_WRITER_H_ #define RAPIDJSON_WRITER_H_ -#include "rapidjson.h" +#include "stream.h" +#include "internal/meta.h" #include "internal/stack.h" #include "internal/strfunc.h" -#include <cstdio> // snprintf() or _sprintf_s() -#include <new> // placement new +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include <new> // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include <nmmintrin.h> +#elif defined(RAPIDJSON_SSE2) +#include <emmintrin.h> +#elif defined(RAPIDJSON_NEON) +#include <arm_neon.h> +#endif #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4127) // conditional expression is constant +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags #endif -namespace rapidjson { +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; //! JSON writer /*! Writer implements the concept Handler. - It generates JSON text by events to an output os. + It generates JSON text by events to an output os. - User may programmatically calls the functions of a writer to generate JSON text. + User may programmatically calls the functions of a writer to generate JSON text. - On the other side, a writer can also be passed to objects that generates events, + On the other side, a writer can also be passed to objects that generates events, - for example Reader::Parse() and Document::Accept(). + for example Reader::Parse() and Document::Accept(). - \tparam OutputStream Type of output stream. - \tparam SourceEncoding Encoding of both source strings. - \tparam TargetEncoding Encoding of and output stream. - \implements Handler + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept */ -template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> > +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> class Writer { public: - typedef typename SourceEncoding::Ch Ch; - - Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(os), level_stack_(allocator, levelDepth * sizeof(Level)) {} - - //@name Implementation of Handler - //@{ - Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } - Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } - Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } - Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } - Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } - Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } - Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } - - Writer& String(const Ch* str, SizeType length, bool copy = false) { - (void)copy; - Prefix(kStringType); - WriteString(str, length); - return *this; - } - - Writer& StartObject() { - Prefix(kObjectType); - new (level_stack_.template Push<Level>()) Level(false); - WriteStartObject(); - return *this; - } - - Writer& EndObject(SizeType memberCount = 0) { - (void)memberCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); - level_stack_.template Pop<Level>(1); - WriteEndObject(); - if (level_stack_.Empty()) // end of json text - os_.Flush(); - return *this; - } - - Writer& StartArray() { - Prefix(kArrayType); - new (level_stack_.template Push<Level>()) Level(true); - WriteStartArray(); - return *this; - } - - Writer& EndArray(SizeType elementCount = 0) { - (void)elementCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); - level_stack_.template Pop<Level>(1); - WriteEndArray(); - if (level_stack_.Empty()) // end of json text - os_.Flush(); - return *this; - } - //@} - - //! Simpler but slower overload. - Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); } + typedef typename SourceEncoding::Ch Ch; + + static const int kDefaultMaxDecimalPlaces = 324; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Writer(Writer&& rhs) : + os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { + rhs.os_ = 0; + } +#endif -protected: - //! Information for each nested level - struct Level { - Level(bool inArray_) : inArray(inArray_), valueCount(0) {} - bool inArray; //!< true if in array, otherwise in object - size_t valueCount; //!< number of values in this level - }; - - static const size_t kDefaultLevelDepth = 32; - - void WriteNull() { - os_.Put('n'); os_.Put('u'); os_.Put('l'); os_.Put('l'); - } - - void WriteBool(bool b) { - if (b) { - os_.Put('t'); os_.Put('r'); os_.Put('u'); os_.Put('e'); - } - else { - os_.Put('f'); os_.Put('a'); os_.Put('l'); os_.Put('s'); os_.Put('e'); - } - } - - void WriteInt(int i) { - if (i < 0) { - os_.Put('-'); - i = -i; - } - WriteUint((unsigned)i); - } - - void WriteUint(unsigned u) { - char buffer[10]; - char *p = buffer; - do { - *p++ = (u % 10) + '0'; - u /= 10; - } while (u > 0); - - do { - --p; - os_.Put(*p); - } while (p != buffer); - } - - void WriteInt64(int64_t i64) { - if (i64 < 0) { - os_.Put('-'); - i64 = -i64; - } - WriteUint64((uint64_t)i64); - } - - void WriteUint64(uint64_t u64) { - char buffer[20]; - char *p = buffer; - do { - *p++ = char(u64 % 10) + '0'; - u64 /= 10; - } while (u64 > 0); - - do { - --p; - os_.Put(*p); - } while (p != buffer); - } - - //! \todo Optimization with custom double-to-string converter. - void WriteDouble(double d) { - char buffer[100]; -#if _MSC_VER - int ret = sprintf_s(buffer, sizeof(buffer), "%g", d); -#else - int ret = snprintf(buffer, sizeof(buffer), "%g", d); + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer<OutputStream> writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } #endif - RAPIDJSON_ASSERT(ret >= 1); - for (int i = 0; i < ret; i++) - os_.Put(buffer[i]); - } - - void WriteString(const Ch* str, SizeType length) { - static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - static const char escape[256] = { + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push<Level>()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object + RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value + level_stack_.template Pop<Level>(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push<Level>()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + return EndValue(WriteEndArray()); + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + Prefix(type); + return EndValue(WriteRawValue(json, length)); + } + + //! Flush the output stream. + /*! + Allows the user to flush the output stream immediately. + */ + void Flush() { + os_->Flush(); + } + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + static const size_t kDefaultLevelDepth = 32; + + bool WriteNull() { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); + } + else { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - //0 1 2 3 4 5 6 7 8 9 A B C D E F - 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 - 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 - 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 - Z16, Z16, // 30~4F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 - Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF #undef Z16 - }; - - os_.Put('\"'); - GenericStringStream<SourceEncoding> is(str); - while (is.Tell() < length) { - const Ch c = is.Peek(); - if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { - is.Take(); - os_.Put('\\'); - os_.Put(escape[(unsigned char)c]); - if (escape[(unsigned char)c] == 'u') { - os_.Put('0'); - os_.Put('0'); - os_.Put(hexDigits[(unsigned char)c >> 4]); - os_.Put(hexDigits[(unsigned char)c & 0xF]); - } - } - else - Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, os_); - } - os_.Put('\"'); - } - - void WriteStartObject() { os_.Put('{'); } - void WriteEndObject() { os_.Put('}'); } - void WriteStartArray() { os_.Put('['); } - void WriteEndArray() { os_.Put(']'); } - - void Prefix(Type type) { - (void)type; - if (level_stack_.GetSize() != 0) { // this value is not at root - Level* level = level_stack_.template Top<Level>(); - if (level->valueCount > 0) { - if (level->inArray) - os_.Put(','); // add comma if it is not the first element in array - else // in object - os_.Put((level->valueCount % 2 == 0) ? ',' : ':'); - } - if (!level->inArray && level->valueCount % 2 == 0) - RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name - level->valueCount++; - } - else - RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); - } - - OutputStream& os_; - internal::Stack<Allocator> level_stack_; + }; + + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); + GenericStringStream<SourceEncoding> is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + return false; + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)])); + if (escape[static_cast<unsigned char>(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : + Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + for (size_t i = 0; i < length; i++) { + RAPIDJSON_ASSERT(json[i] != '\0'); + PutUnsafe(*os_, json[i]); + } + return true; + } + + void Prefix(Type type) { + (void)type; + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root + Level* level = level_stack_.template Top<Level>(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + Flush(); + return ret; + } + + OutputStream* os_; + internal::Stack<StackAllocator> level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; private: - // Prohibit assignment for VC C4512 warning - Writer& operator=(const Writer& w); + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); }; -} // namespace rapidjson +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer<StringBuffer>::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast<size_t>(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast<size_t>(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast<size_t>(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast<size_t>(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast<size_t>(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast<SizeType>(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast<char*>(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#elif defined(RAPIDJSON_NEON) +template<> +inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (; p != endAligned; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract + + SizeType len = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + unsigned lz = (unsigned)__builtin_clzll(high); + len = 8 + (lz >> 3); + escaped = true; + } + } else { + unsigned lz = (unsigned)__builtin_clzll(low); + len = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + char* q = reinterpret_cast<char*>(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // RAPIDJSON_NEON + +RAPIDJSON_NAMESPACE_END #ifdef _MSC_VER -#pragma warning(pop) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP #endif #endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Source/ThirdParty/rapidjson/license.txt b/Source/ThirdParty/rapidjson/license.txt new file mode 100644 index 0000000000..7ccc161c84 --- /dev/null +++ b/Source/ThirdParty/rapidjson/license.txt @@ -0,0 +1,57 @@ +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* 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. +* Neither the name of 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 REGENTS 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 REGENTS AND 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. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +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 shall be used for Good, not Evil. + +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. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +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. diff --git a/Source/Tools/AssetImporter/AssetImporter.cpp b/Source/Tools/AssetImporter/AssetImporter.cpp index b89d42bbab..52f2e770a2 100644 --- a/Source/Tools/AssetImporter/AssetImporter.cpp +++ b/Source/Tools/AssetImporter/AssetImporter.cpp @@ -947,8 +947,9 @@ void BuildAndSaveModel(OutModel& model) aiMatrix4x4 transform = boneNode->mTransformation; // Make the root bone transform relative to the model's root node, if it is not already + // (in case there are nodes between that are not accounted for otherwise) if (boneNode == model.rootBone_) - transform = GetDerivedTransform(boneNode, model.rootNode_); + transform = GetDerivedTransform(boneNode, model.rootNode_, false); GetPosRotScale(transform, newBone.initialPosition_, newBone.initialRotation_, newBone.initialScale_); @@ -1050,18 +1051,42 @@ void BuildAndSaveAnimations(OutModel* model) aiNodeAnim* channel = anim->mChannels[j]; String channelName = FromAIString(channel->mNodeName); aiNode* boneNode = 0; - bool isRootBone = false; - + if (model) { - unsigned boneIndex = GetBoneIndex(*model, channelName); - if (boneIndex == M_MAX_UNSIGNED) + unsigned boneIndex; + unsigned pos = channelName.Find("_$AssimpFbx$"); + + if (!suppressFbxPivotNodes_ || pos == String::NPOS) { - PrintLine("Warning: skipping animation track " + channelName + " not found in model skeleton"); - continue; + boneIndex = GetBoneIndex(*model, channelName); + if (boneIndex == M_MAX_UNSIGNED) + { + PrintLine("Warning: skipping animation track " + channelName + " not found in model skeleton"); + outAnim->RemoveTrack(channelName); + continue; + } + boneNode = model->bones_[boneIndex]; + } + else + { + channelName = channelName.Substring(0, pos); + + // every first $fbx animation channel for a bone will consolidate other $fbx animation to a single channel + // skip subsequent $fbx animation channel for the same bone + if (outAnim->GetTrack(channelName) != NULL) + continue; + + boneIndex = GetPivotlessBoneIndex(*model, channelName); + if (boneIndex == M_MAX_UNSIGNED) + { + PrintLine("Warning: skipping animation track " + channelName + " not found in model skeleton"); + outAnim->RemoveTrack(channelName); + continue; + } + + boneNode = model->pivotlessBones_[boneIndex]; } - boneNode = model->bones_[boneIndex]; - isRootBone = boneIndex == 0; } else { @@ -1164,40 +1189,42 @@ void BuildAndSaveAnimations(OutModel* model) aiQuaternion rot; boneTransform.Decompose(scale, rot, pos); // Then apply the active channels - if (track.channelMask_ & CHANNEL_POSITION && k < channel->mNumPositionKeys) + if (track->channelMask_ & CHANNEL_POSITION && k < channel->mNumPositionKeys) pos = channel->mPositionKeys[k].mValue; - if (track.channelMask_ & CHANNEL_ROTATION && k < channel->mNumRotationKeys) + if (track->channelMask_ & CHANNEL_ROTATION && k < channel->mNumRotationKeys) rot = channel->mRotationKeys[k].mValue; - if (track.channelMask_ & CHANNEL_SCALE && k < channel->mNumScalingKeys) + if (track->channelMask_ & CHANNEL_SCALE && k < channel->mNumScalingKeys) scale = channel->mScalingKeys[k].mValue; - - // If root bone, transform with the model root node transform - if (model && isRootBone) + + // If root bone, transform with nodes in between model root node (if any) + if (model && boneNode == model->rootBone_) { aiMatrix4x4 transMat, scaleMat, rotMat; aiMatrix4x4::Translation(pos, transMat); aiMatrix4x4::Scaling(scale, scaleMat); rotMat = aiMatrix4x4(rot.GetMatrix()); aiMatrix4x4 tform = transMat * rotMat * scaleMat; - tform = GetDerivedTransform(tform, boneNode, model->rootNode_); - tform.Decompose(scale, rot, pos); + aiMatrix4x4 tformOld = tform; + tform = GetDerivedTransform(tform, boneNode, model->rootNode_, false); + // Do not decompose if did not actually change + if (tform != tformOld) + tform.Decompose(scale, rot, pos); } - - if (track.channelMask_ & CHANNEL_POSITION) + + if (track->channelMask_ & CHANNEL_POSITION) kf.position_ = ToVector3(pos); - if (track.channelMask_ & CHANNEL_ROTATION) + if (track->channelMask_ & CHANNEL_ROTATION) kf.rotation_ = ToQuaternion(rot); - if (track.channelMask_ & CHANNEL_SCALE) + if (track->channelMask_ & CHANNEL_SCALE) kf.scale_ = ToVector3(scale); - - track.keyFrames_.Push(kf); + if (kf.time_ >= thisImportStartTime && kf.time_ <= thisImportEndTime) + { + kf.time_ = (kf.time_ - thisImportStartTime) * tickConversion; + track->keyFrames_.Push(kf); + } } - - tracks.Push(track); } - - outAnim->SetTracks(tracks); - + File outFile(context_); if (!outFile.Open(animOutName, FILE_WRITE)) ErrorExit("Could not open output file " + animOutName); diff --git a/Source/Tools/PackageTool/PackageTool.cpp b/Source/Tools/PackageTool/PackageTool.cpp index 4b9dd491c4..82beb98eb8 100755 --- a/Source/Tools/PackageTool/PackageTool.cpp +++ b/Source/Tools/PackageTool/PackageTool.cpp @@ -24,18 +24,17 @@ #include <Atomic/Core/Context.h> #include <Atomic/Container/ArrayPtr.h> +#include <Atomic/Core/ProcessUtils.h> #include <Atomic/IO/File.h> #include <Atomic/IO/FileSystem.h> -#include <Atomic/Core/ProcessUtils.h> +#include <Atomic/IO/PackageFile.h> #ifdef WIN32 #include <windows.h> #endif -#include <cstdio> -#include <cstring> -#include <ThirdParty/LZ4/lz4.h> -#include <ThirdParty/LZ4/lz4hc.h> +#include <LZ4/lz4.h> +#include <LZ4/lz4hc.h> #include <Atomic/DebugNew.h> @@ -57,6 +56,7 @@ String basePath_; Vector<FileEntry> entries_; unsigned checksum_ = 0; bool compress_ = false; +bool quiet_ = false; unsigned blockSize_ = COMPRESSED_BLOCK_SIZE; String ignoreExtensions_[] = { @@ -74,13 +74,13 @@ void WriteHeader(File& dest); int main(int argc, char** argv) { Vector<String> arguments; - + #ifdef WIN32 arguments = ParseArguments(GetCommandLineW()); #else arguments = ParseArguments(argc, argv); #endif - + Run(arguments); return 0; } @@ -93,10 +93,19 @@ void Run(const Vector<String>& arguments) "\n" "Options:\n" "-c Enable package file LZ4 compression\n" + "-q Enable quiet mode\n" + "\n" + "Basepath is an optional prefix that will be added to the file entries.\n\n" + "Alternative output usage: PackageTool <output option> <package name>\n" + "Output option:\n" + "-i Output package file information\n" + "-l Output file names (including their paths) contained in the package\n" + "-L Similar to -l but also output compression ratio (compressed package file only)\n" ); - + const String& dirName = arguments[0]; const String& packageName = arguments[1]; + bool isOutputMode = arguments[0].Length() == 2 && arguments[0][0] == '-'; if (arguments.Size() > 2) { for (unsigned i = 2; i < arguments.Size(); ++i) @@ -112,38 +121,88 @@ void Run(const Vector<String>& arguments) case 'c': compress_ = true; break; + case 'q': + quiet_ = true; + break; + default: + ErrorExit("Unrecognized option"); } } } } } - - PrintLine("Scanning directory " + dirName + " for files"); - - // Get the file list recursively - Vector<String> fileNames; - fileSystem_->ScanDir(fileNames, dirName, "*.*", SCAN_FILES, true); - if (!fileNames.Size()) - ErrorExit("No files found"); - - // Check for extensions to ignore - for (unsigned i = fileNames.Size() - 1; i < fileNames.Size(); --i) + + if (!isOutputMode) { - String extension = GetExtension(fileNames[i]); - for (unsigned j = 0; ignoreExtensions_[j].Length(); ++j) + if (!quiet_) + PrintLine("Scanning directory " + dirName + " for files"); + + // Get the file list recursively + Vector<String> fileNames; + fileSystem_->ScanDir(fileNames, dirName, "*.*", SCAN_FILES, true); + if (!fileNames.Size()) + ErrorExit("No files found"); + + // Check for extensions to ignore + for (unsigned i = fileNames.Size() - 1; i < fileNames.Size(); --i) { - if (extension == ignoreExtensions_[j]) + String extension = GetExtension(fileNames[i]); + for (unsigned j = 0; ignoreExtensions_[j].Length(); ++j) { - fileNames.Erase(fileNames.Begin() + i); - break; + if (extension == ignoreExtensions_[j]) + { + fileNames.Erase(fileNames.Begin() + i); + break; + } + } + } + + for (unsigned i = 0; i < fileNames.Size(); ++i) + ProcessFile(fileNames[i], dirName); + + WritePackageFile(packageName, dirName); + } + else + { + SharedPtr<PackageFile> packageFile(new PackageFile(context_, packageName)); + bool outputCompressionRatio = false; + switch (arguments[0][1]) + { + case 'i': + PrintLine("Number of files: " + String(packageFile->GetNumFiles())); + PrintLine("File data size: " + String(packageFile->GetTotalDataSize())); + PrintLine("Package size: " + String(packageFile->GetTotalSize())); + PrintLine("Checksum: " + String(packageFile->GetChecksum())); + PrintLine("Compressed: " + String(packageFile->IsCompressed() ? "yes" : "no")); + break; + case 'L': + if (!packageFile->IsCompressed()) + ErrorExit("Invalid output option: -L is applicable for compressed package file only"); + outputCompressionRatio = true; + // Fallthrough + case 'l': + { + const HashMap<String, PackageEntry>& entries = packageFile->GetEntries(); + for (HashMap<String, PackageEntry>::ConstIterator i = entries.Begin(); i != entries.End();) + { + HashMap<String, PackageEntry>::ConstIterator current = i++; + String fileEntry(current->first_); + if (outputCompressionRatio) + { + unsigned compressedSize = + (i == entries.End() ? packageFile->GetTotalSize() - sizeof(unsigned) : i->second_.offset_) - + current->second_.offset_; + fileEntry.AppendWithFormat("\tin: %u\tout: %u\tratio: %f", current->second_.size_, compressedSize, + compressedSize ? 1.f * current->second_.size_ / compressedSize : 0.f); + } + PrintLine(fileEntry); + } } + break; + default: + ErrorExit("Unrecognized output option"); } } - - for (unsigned i = 0; i < fileNames.Size(); ++i) - ProcessFile(fileNames[i], dirName); - - WritePackageFile(packageName, dirName); } void ProcessFile(const String& fileName, const String& rootDir) @@ -154,7 +213,7 @@ void ProcessFile(const String& fileName, const String& rootDir) ErrorExit("Could not open file " + fileName); if (!file.GetSize()) return; - + FileEntry newEntry; newEntry.name_ = fileName; newEntry.offset_ = 0; // Offset not yet known @@ -165,103 +224,116 @@ void ProcessFile(const String& fileName, const String& rootDir) void WritePackageFile(const String& fileName, const String& rootDir) { - PrintLine("Writing package"); - + if (!quiet_) + PrintLine("Writing package"); + File dest(context_); if (!dest.Open(fileName, FILE_WRITE)) ErrorExit("Could not open output file " + fileName); - + // Write ID, number of files & placeholder for checksum WriteHeader(dest); - + for (unsigned i = 0; i < entries_.Size(); ++i) { // Write entry (correct offset is still unknown, will be filled in later) - dest.WriteString(entries_[i].name_); + dest.WriteString(basePath_ + entries_[i].name_); dest.WriteUInt(entries_[i].offset_); dest.WriteUInt(entries_[i].size_); dest.WriteUInt(entries_[i].checksum_); } - + unsigned totalDataSize = 0; - + unsigned lastOffset; + // Write file data, calculate checksums & correct offsets for (unsigned i = 0; i < entries_.Size(); ++i) { - entries_[i].offset_ = dest.GetSize(); + lastOffset = entries_[i].offset_ = dest.GetSize(); String fileFullPath = rootDir + "/" + entries_[i].name_; - + File srcFile(context_, fileFullPath); if (!srcFile.IsOpen()) ErrorExit("Could not open file " + fileFullPath); - + unsigned dataSize = entries_[i].size_; totalDataSize += dataSize; SharedArrayPtr<unsigned char> buffer(new unsigned char[dataSize]); - + if (srcFile.Read(&buffer[0], dataSize) != dataSize) ErrorExit("Could not read file " + fileFullPath); srcFile.Close(); - + for (unsigned j = 0; j < dataSize; ++j) { checksum_ = SDBMHash(checksum_, buffer[j]); entries_[i].checksum_ = SDBMHash(entries_[i].checksum_, buffer[j]); } - + if (!compress_) { - PrintLine(entries_[i].name_ + " size " + String(dataSize)); + if (!quiet_) + PrintLine(entries_[i].name_ + " size " + String(dataSize)); dest.Write(&buffer[0], entries_[i].size_); } else { SharedArrayPtr<unsigned char> compressBuffer(new unsigned char[LZ4_compressBound(blockSize_)]); - + unsigned pos = 0; - unsigned totalPackedBytes = 0; - + while (pos < dataSize) { unsigned unpackedSize = blockSize_; if (pos + unpackedSize > dataSize) unpackedSize = dataSize - pos; - - unsigned packedSize = LZ4_compressHC((const char*)&buffer[pos], (char*)compressBuffer.Get(), unpackedSize); + + unsigned packedSize = (unsigned)LZ4_compressHC((const char*)&buffer[pos], (char*)compressBuffer.Get(), unpackedSize); if (!packedSize) ErrorExit("LZ4 compression failed for file " + entries_[i].name_ + " at offset " + String(pos)); - - dest.WriteUShort(unpackedSize); - dest.WriteUShort(packedSize); + + dest.WriteUShort((unsigned short)unpackedSize); + dest.WriteUShort((unsigned short)packedSize); dest.Write(compressBuffer.Get(), packedSize); - totalPackedBytes += 6 + packedSize; - + pos += unpackedSize; } - - PrintLine(entries_[i].name_ + " in " + String(dataSize) + " out " + String(totalPackedBytes)); + + if (!quiet_) + { + unsigned totalPackedBytes = dest.GetSize() - lastOffset; + String fileEntry(entries_[i].name_); + fileEntry.AppendWithFormat("\tin: %u\tout: %u\tratio: %f", dataSize, totalPackedBytes, + totalPackedBytes ? 1.f * dataSize / totalPackedBytes : 0.f); + PrintLine(fileEntry); + } } } - + // Write package size to the end of file to allow finding it linked to an executable file unsigned currentSize = dest.GetSize(); dest.WriteUInt(currentSize + sizeof(unsigned)); - + // Write header again with correct offsets & checksums dest.Seek(0); WriteHeader(dest); - + for (unsigned i = 0; i < entries_.Size(); ++i) { - dest.WriteString(entries_[i].name_); + dest.WriteString(basePath_ + entries_[i].name_); dest.WriteUInt(entries_[i].offset_); dest.WriteUInt(entries_[i].size_); dest.WriteUInt(entries_[i].checksum_); } - - PrintLine("Number of files " + String(entries_.Size())); - PrintLine("File data size " + String(totalDataSize)); - PrintLine("Package size " + String(dest.GetSize())); + + if (!quiet_) + { + PrintLine("Number of files: " + String(entries_.Size())); + PrintLine("File data size: " + String(totalDataSize)); + PrintLine("Package size: " + String(dest.GetSize())); + PrintLine("Checksum: " + String(checksum_)); + PrintLine("Compressed: " + String(compress_ ? "yes" : "no")); + } } void WriteHeader(File& dest)