From d6d51b73ee2f182bbb5282587323fe392ffc58ef Mon Sep 17 00:00:00 2001 From: Mikko Mononen Date: Tue, 13 Apr 2010 11:11:22 +0000 Subject: [PATCH] Slideshow stuff for demo purposes. --- .../Xcode/Recast.xcodeproj/memon.pbxuser | 1989 ++++----- .../Recast.xcodeproj/memon.perspectivev3 | 132 +- .../Xcode/Recast.xcodeproj/project.pbxproj | 18 +- RecastDemo/Contrib/stb_image.h | 3893 +++++++++++++++++ RecastDemo/Include/Filelist.h | 35 + RecastDemo/Include/SlideShow.h | 53 + RecastDemo/Source/Filelist.cpp | 100 + RecastDemo/Source/SlideShow.cpp | 159 + RecastDemo/Source/main.cpp | 112 +- 9 files changed, 5136 insertions(+), 1355 deletions(-) create mode 100644 RecastDemo/Contrib/stb_image.h create mode 100644 RecastDemo/Include/Filelist.h create mode 100644 RecastDemo/Include/SlideShow.h create mode 100644 RecastDemo/Source/Filelist.cpp create mode 100644 RecastDemo/Source/SlideShow.cpp diff --git a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser index cc81778..7fa2b6d 100644 --- a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser +++ b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser @@ -121,8 +121,8 @@ PBXFindDataSource_LocationID, ); }; - PBXPerProjectTemplateStateSaveDate = 292835359; - PBXWorkspaceStateSaveDate = 292835359; + PBXPerProjectTemplateStateSaveDate = 292847220; + PBXWorkspaceStateSaveDate = 292847220; }; perUserProjectItems = { 6BBB4A94115B4F3400CF791D = 6BBB4A94115B4F3400CF791D /* PBXTextBookmark */; @@ -144,11 +144,8 @@ 6BBB4AA6115B4F3400CF791D = 6BBB4AA6115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AA7115B4F3400CF791D = 6BBB4AA7115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AA8115B4F3400CF791D = 6BBB4AA8115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AA9115B4F3400CF791D = 6BBB4AA9115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AAA115B4F3400CF791D = 6BBB4AAA115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AAB115B4F3400CF791D = 6BBB4AAB115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AAC115B4F3400CF791D = 6BBB4AAC115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AAF115B4F3400CF791D = 6BBB4AAF115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AB0115B4F3400CF791D = 6BBB4AB0115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AB1115B4F3400CF791D = 6BBB4AB1115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AB2115B4F3400CF791D = 6BBB4AB2115B4F3400CF791D /* PBXTextBookmark */; @@ -176,12 +173,7 @@ 6BBB4AD2115B4F3400CF791D = 6BBB4AD2115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AD3115B4F3400CF791D = 6BBB4AD3115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AD4115B4F3400CF791D = 6BBB4AD4115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AD5115B4F3400CF791D = 6BBB4AD5115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AD6115B4F3400CF791D = 6BBB4AD6115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AD7115B4F3400CF791D = 6BBB4AD7115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AD8115B4F3400CF791D = 6BBB4AD8115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AD9115B4F3400CF791D = 6BBB4AD9115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4ADB115B4F3400CF791D = 6BBB4ADB115B4F3400CF791D /* PBXTextBookmark */; 6BBB4ADD115B4F3400CF791D = 6BBB4ADD115B4F3400CF791D /* PBXTextBookmark */; 6BBB4ADE115B4F3400CF791D = 6BBB4ADE115B4F3400CF791D /* PBXTextBookmark */; 6BBB4ADF115B4F3400CF791D = 6BBB4ADF115B4F3400CF791D /* PBXTextBookmark */; @@ -203,11 +195,7 @@ 6BBB4AEF115B4F3400CF791D = 6BBB4AEF115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AF0115B4F3400CF791D = 6BBB4AF0115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AF1115B4F3400CF791D = 6BBB4AF1115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AF2115B4F3400CF791D = 6BBB4AF2115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AF3115B4F3400CF791D = 6BBB4AF3115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AF4115B4F3400CF791D = 6BBB4AF4115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AF5115B4F3400CF791D = 6BBB4AF5115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4AF6115B4F3400CF791D = 6BBB4AF6115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AF7115B4F3400CF791D = 6BBB4AF7115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AF8115B4F3400CF791D = 6BBB4AF8115B4F3400CF791D /* PBXTextBookmark */; 6BBB4AF9115B4F3400CF791D = 6BBB4AF9115B4F3400CF791D /* PBXTextBookmark */; @@ -234,121 +222,86 @@ 6BBB4B0F115B4F3400CF791D = 6BBB4B0F115B4F3400CF791D /* PBXTextBookmark */; 6BBB4B10115B4F3400CF791D = 6BBB4B10115B4F3400CF791D /* PBXTextBookmark */; 6BBB4B11115B4F3400CF791D = 6BBB4B11115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4B14115B4F3400CF791D = 6BBB4B14115B4F3400CF791D /* PBXTextBookmark */; - 6BBB4B2D115B5B3200CF791D = 6BBB4B2D115B5B3200CF791D /* PBXTextBookmark */; 6BBB4B3A115B5BFA00CF791D = 6BBB4B3A115B5BFA00CF791D /* PBXTextBookmark */; - 6BBB4B3C115B5BFA00CF791D = 6BBB4B3C115B5BFA00CF791D /* PBXTextBookmark */; - 6BBB4B41115B5D4B00CF791D = 6BBB4B41115B5D4B00CF791D /* PBXTextBookmark */; - 6BBB4B43115B5D4B00CF791D = 6BBB4B43115B5D4B00CF791D /* PBXTextBookmark */; - 6BBB4B45115B5D4B00CF791D = 6BBB4B45115B5D4B00CF791D /* PBXTextBookmark */; - 6BBB4B47115B5D4B00CF791D = 6BBB4B47115B5D4B00CF791D /* PBXTextBookmark */; - 6BBB4B49115B5D4B00CF791D = 6BBB4B49115B5D4B00CF791D /* PBXTextBookmark */; - 6BBB4B4E115B5DD900CF791D = 6BBB4B4E115B5DD900CF791D /* PBXTextBookmark */; - 6BBB4B5E115B609F00CF791D = 6BBB4B5E115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B60115B609F00CF791D = 6BBB4B60115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B62115B609F00CF791D = 6BBB4B62115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B64115B609F00CF791D = 6BBB4B64115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B66115B609F00CF791D = 6BBB4B66115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B68115B609F00CF791D = 6BBB4B68115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B6A115B609F00CF791D = 6BBB4B6A115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B6C115B609F00CF791D = 6BBB4B6C115B609F00CF791D /* PBXTextBookmark */; - 6BBB4B6E115B609F00CF791D = 6BBB4B6E115B609F00CF791D /* PBXTextBookmark */; 6BBB4B7A115B639200CF791D = 6BBB4B7A115B639200CF791D /* PBXTextBookmark */; 6BBB4B7D115B639200CF791D = 6BBB4B7D115B639200CF791D /* PBXTextBookmark */; - 6BBB4B7E115B639200CF791D = 6BBB4B7E115B639200CF791D /* PBXTextBookmark */; 6BBB4B7F115B639200CF791D = 6BBB4B7F115B639200CF791D /* PBXTextBookmark */; - 6BBB4B85115B639200CF791D = 6BBB4B85115B639200CF791D /* PBXTextBookmark */; 6BBB4B87115B639200CF791D = 6BBB4B87115B639200CF791D /* PBXTextBookmark */; - 6BBB4B88115B639200CF791D = 6BBB4B88115B639200CF791D /* PBXTextBookmark */; - 6BBB4B8A115B639200CF791D = 6BBB4B8A115B639200CF791D /* PBXTextBookmark */; - 6BBB4B8C115B639200CF791D = 6BBB4B8C115B639200CF791D /* PBXTextBookmark */; - 6BBB4B8E115B639200CF791D = 6BBB4B8E115B639200CF791D /* PBXTextBookmark */; - 6BBB4B90115B639200CF791D = 6BBB4B90115B639200CF791D /* PBXTextBookmark */; - 6BBB4B92115B639200CF791D = 6BBB4B92115B639200CF791D /* PBXTextBookmark */; - 6BBB4B95115B639200CF791D = 6BBB4B95115B639200CF791D /* PBXTextBookmark */; - 6BBB4B96115B639200CF791D = 6BBB4B96115B639200CF791D /* PBXTextBookmark */; - 6BBB4B97115B639200CF791D = 6BBB4B97115B639200CF791D /* PBXTextBookmark */; - 6BBB4B98115B639200CF791D = 6BBB4B98115B639200CF791D /* PBXTextBookmark */; - 6BBB4B99115B639200CF791D = 6BBB4B99115B639200CF791D /* PBXTextBookmark */; - 6BBB4B9A115B639200CF791D = 6BBB4B9A115B639200CF791D /* PBXTextBookmark */; - 6BBB4B9B115B639200CF791D = 6BBB4B9B115B639200CF791D /* PBXTextBookmark */; - 6BBB4B9C115B639200CF791D = 6BBB4B9C115B639200CF791D /* PBXTextBookmark */; - 6BBB4B9D115B639200CF791D = 6BBB4B9D115B639200CF791D /* PBXTextBookmark */; - 6BBB4B9E115B639200CF791D = 6BBB4B9E115B639200CF791D /* PBXTextBookmark */; - 6BBB4B9F115B639200CF791D = 6BBB4B9F115B639200CF791D /* PBXTextBookmark */; - 6BBB4BA0115B639200CF791D = 6BBB4BA0115B639200CF791D /* PBXTextBookmark */; - 6BBB4BA1115B639200CF791D = 6BBB4BA1115B639200CF791D /* PBXTextBookmark */; - 6BBB4BA2115B639200CF791D = 6BBB4BA2115B639200CF791D /* PBXTextBookmark */; - 6BBB4BA3115B639200CF791D = 6BBB4BA3115B639200CF791D /* PBXTextBookmark */; - 6BBB4BB1115B649700CF791D = 6BBB4BB1115B649700CF791D /* PBXTextBookmark */; - 6BBB4BCC115B653C00CF791D = 6BBB4BCC115B653C00CF791D /* PBXTextBookmark */; 6BBB4BDA115B679300CF791D = 6BBB4BDA115B679300CF791D /* PBXTextBookmark */; - 6BBB4BE0115B679300CF791D = 6BBB4BE0115B679300CF791D /* PBXTextBookmark */; - 6BBB4BE1115B679300CF791D = 6BBB4BE1115B679300CF791D /* PBXTextBookmark */; - 6BBB4BE3115B679300CF791D = 6BBB4BE3115B679300CF791D /* PBXTextBookmark */; 6BBB4BE6115B69BE00CF791D = 6BBB4BE6115B69BE00CF791D /* PBXTextBookmark */; - 6BBB4BE8115B69BE00CF791D = 6BBB4BE8115B69BE00CF791D /* PBXTextBookmark */; - 6BBB4BED115B6B8A00CF791D = 6BBB4BED115B6B8A00CF791D /* PBXTextBookmark */; - 6BBB4BEF115B6B8A00CF791D = 6BBB4BEF115B6B8A00CF791D /* PBXTextBookmark */; - 6BBB4BF1115B6B8A00CF791D = 6BBB4BF1115B6B8A00CF791D /* PBXTextBookmark */; - 6BBB4BF3115B6B8A00CF791D = 6BBB4BF3115B6B8A00CF791D /* PBXTextBookmark */; - 6BBB4BF5115B6B8A00CF791D = 6BBB4BF5115B6B8A00CF791D /* PBXTextBookmark */; - 6BBB4BF7115B6B8A00CF791D = 6BBB4BF7115B6B8A00CF791D /* PBXTextBookmark */; - 6BBB4BFF115B6D9C00CF791D = 6BBB4BFF115B6D9C00CF791D /* PBXTextBookmark */; - 6BBB4C01115B6D9C00CF791D = 6BBB4C01115B6D9C00CF791D /* PBXTextBookmark */; - 6BBB4C03115B6D9C00CF791D = 6BBB4C03115B6D9C00CF791D /* PBXTextBookmark */; - 6BBB4C0A115B6E0200CF791D = 6BBB4C0A115B6E0200CF791D /* PBXTextBookmark */; - 6BBB4C10115B72F400CF791D = 6BBB4C10115B72F400CF791D /* PBXTextBookmark */; - 6BBB4C12115B72F400CF791D = 6BBB4C12115B72F400CF791D /* PBXTextBookmark */; - 6BBB4C17115B758400CF791D = 6BBB4C17115B758400CF791D /* PBXTextBookmark */; - 6BBB4C18115B758400CF791D = 6BBB4C18115B758400CF791D /* PBXTextBookmark */; - 6BBB4C19115B758400CF791D = 6BBB4C19115B758400CF791D /* PBXTextBookmark */; - 6BBB4C1A115B758400CF791D = 6BBB4C1A115B758400CF791D /* PBXTextBookmark */; - 6BBB4C1B115B758400CF791D = 6BBB4C1B115B758400CF791D /* PBXTextBookmark */; - 6BBB4C22115B784C00CF791D = 6BBB4C22115B784C00CF791D /* PBXTextBookmark */; - 6BBB4C24115B784C00CF791D = 6BBB4C24115B784C00CF791D /* PBXTextBookmark */; - 6BBB4C26115B784C00CF791D = 6BBB4C26115B784C00CF791D /* PBXTextBookmark */; - 6BBB4C28115B784C00CF791D = 6BBB4C28115B784C00CF791D /* PBXTextBookmark */; - 6BBB4C2A115B784C00CF791D = 6BBB4C2A115B784C00CF791D /* PBXTextBookmark */; - 6BBB4C2C115B784C00CF791D = 6BBB4C2C115B784C00CF791D /* PBXTextBookmark */; 6BBB4C34115B7A3D00CF791D = 6BBB4C34115B7A3D00CF791D /* PBXTextBookmark */; 6BBB4C38115B7A3D00CF791D = 6BBB4C38115B7A3D00CF791D /* PBXTextBookmark */; 6BBB4C3B115B7A3D00CF791D = 6BBB4C3B115B7A3D00CF791D /* PBXTextBookmark */; - 6BBB4C3F115B7A3D00CF791D = 6BBB4C3F115B7A3D00CF791D /* PBXTextBookmark */; - 6BBB4C41115B7A3D00CF791D = 6BBB4C41115B7A3D00CF791D /* PBXTextBookmark */; - 6BBB4C43115B7A3D00CF791D = 6BBB4C43115B7A3D00CF791D /* PBXTextBookmark */; - 6BBB4C58115B8BF700CF791D = 6BBB4C58115B8BF700CF791D /* PBXTextBookmark */; 6BBB4C59115B8BF700CF791D = 6BBB4C59115B8BF700CF791D /* PBXTextBookmark */; - 6BBB4C5A115B8BF700CF791D = 6BBB4C5A115B8BF700CF791D /* PBXTextBookmark */; - 6BBB4C5B115B8BF700CF791D = 6BBB4C5B115B8BF700CF791D /* PBXTextBookmark */; - 6BBB4C5C115B8BF700CF791D = 6BBB4C5C115B8BF700CF791D /* PBXTextBookmark */; - 6BBB4C5D115B8BF700CF791D = 6BBB4C5D115B8BF700CF791D /* PBXTextBookmark */; - 6BBB4C5E115B8BF700CF791D = 6BBB4C5E115B8BF700CF791D /* PBXTextBookmark */; - 6BBB4C61115B906700CF791D = 6BBB4C61115B906700CF791D /* PBXTextBookmark */; - 6BED8AD41174509800582F38 /* PBXTextBookmark */ = 6BED8AD41174509800582F38 /* PBXTextBookmark */; - 6BED8AD51174509800582F38 /* PBXTextBookmark */ = 6BED8AD51174509800582F38 /* PBXTextBookmark */; - 6BED8AD61174509800582F38 /* PBXTextBookmark */ = 6BED8AD61174509800582F38 /* PBXTextBookmark */; - 6BED8AD71174509800582F38 /* PBXTextBookmark */ = 6BED8AD71174509800582F38 /* PBXTextBookmark */; - 6BED8AD81174509D00582F38 /* PBXTextBookmark */ = 6BED8AD81174509D00582F38 /* PBXTextBookmark */; - 6BED8ADB1174514E00582F38 /* PBXTextBookmark */ = 6BED8ADB1174514E00582F38 /* PBXTextBookmark */; - 6BED8ADC1174514E00582F38 /* PBXTextBookmark */ = 6BED8ADC1174514E00582F38 /* PBXTextBookmark */; - 6BED8ADD1174514E00582F38 /* PBXTextBookmark */ = 6BED8ADD1174514E00582F38 /* PBXTextBookmark */; - 6BED8ADE1174514E00582F38 /* PBXTextBookmark */ = 6BED8ADE1174514E00582F38 /* PBXTextBookmark */; - 6BED8ADF1174514E00582F38 /* PBXTextBookmark */ = 6BED8ADF1174514E00582F38 /* PBXTextBookmark */; - 6BED8AE01174515300582F38 /* PBXTextBookmark */ = 6BED8AE01174515300582F38 /* PBXTextBookmark */; - 6BED8AE2117451EB00582F38 /* PBXTextBookmark */ = 6BED8AE2117451EB00582F38 /* PBXTextBookmark */; - 6BED8AE3117451EB00582F38 /* PBXTextBookmark */ = 6BED8AE3117451EB00582F38 /* PBXTextBookmark */; - 6BED8AE4117451EB00582F38 /* PBXTextBookmark */ = 6BED8AE4117451EB00582F38 /* PBXTextBookmark */; - 6BED8AE5117451EB00582F38 /* PBXTextBookmark */ = 6BED8AE5117451EB00582F38 /* PBXTextBookmark */; - 6BED8AEE117455CB00582F38 /* PBXTextBookmark */ = 6BED8AEE117455CB00582F38 /* PBXTextBookmark */; - 6BED8AEF117455CB00582F38 /* PBXTextBookmark */ = 6BED8AEF117455CB00582F38 /* PBXTextBookmark */; - 6BED8AF0117455CB00582F38 /* PBXTextBookmark */ = 6BED8AF0117455CB00582F38 /* PBXTextBookmark */; - 6BED8AF1117455CB00582F38 /* PBXTextBookmark */ = 6BED8AF1117455CB00582F38 /* PBXTextBookmark */; - 6BED8AF21174567000582F38 /* PBXTextBookmark */ = 6BED8AF21174567000582F38 /* PBXTextBookmark */; - 6BED8AF31174567000582F38 /* PBXTextBookmark */ = 6BED8AF31174567000582F38 /* PBXTextBookmark */; - 6BED8AF41174567000582F38 /* PBXTextBookmark */ = 6BED8AF41174567000582F38 /* PBXTextBookmark */; - 6BED8AF51174567000582F38 /* PBXTextBookmark */ = 6BED8AF51174567000582F38 /* PBXTextBookmark */; - 6BED8AF81174570F00582F38 /* PBXTextBookmark */ = 6BED8AF81174570F00582F38 /* PBXTextBookmark */; + 6BED8AD41174509800582F38 = 6BED8AD41174509800582F38 /* PBXTextBookmark */; + 6BED8AD61174509800582F38 = 6BED8AD61174509800582F38 /* PBXTextBookmark */; + 6BED8AE2117451EB00582F38 = 6BED8AE2117451EB00582F38 /* PBXTextBookmark */; + 6BED8AEE117455CB00582F38 = 6BED8AEE117455CB00582F38 /* PBXTextBookmark */; + 6BED8AF0117455CB00582F38 = 6BED8AF0117455CB00582F38 /* PBXTextBookmark */; + 6BED8AF21174567000582F38 = 6BED8AF21174567000582F38 /* PBXTextBookmark */; + 6BF5F231117474CF000502A6 = 6BF5F231117474CF000502A6 /* PBXTextBookmark */; + 6BF5F233117474CF000502A6 = 6BF5F233117474CF000502A6 /* PBXTextBookmark */; + 6BF5F27011747CFA000502A6 = 6BF5F27011747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27111747CFA000502A6 = 6BF5F27111747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27211747CFA000502A6 = 6BF5F27211747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27311747CFA000502A6 = 6BF5F27311747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27411747CFA000502A6 = 6BF5F27411747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27611747CFA000502A6 = 6BF5F27611747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27711747CFA000502A6 = 6BF5F27711747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27811747CFA000502A6 = 6BF5F27811747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27911747CFA000502A6 = 6BF5F27911747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27A11747CFA000502A6 = 6BF5F27A11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27B11747CFA000502A6 = 6BF5F27B11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27C11747CFA000502A6 = 6BF5F27C11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27D11747CFA000502A6 = 6BF5F27D11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27E11747CFA000502A6 = 6BF5F27E11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F27F11747CFA000502A6 = 6BF5F27F11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28011747CFA000502A6 = 6BF5F28011747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28111747CFA000502A6 = 6BF5F28111747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28211747CFA000502A6 = 6BF5F28211747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28311747CFA000502A6 = 6BF5F28311747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28411747CFA000502A6 = 6BF5F28411747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28511747CFA000502A6 = 6BF5F28511747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28611747CFA000502A6 = 6BF5F28611747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28711747CFA000502A6 = 6BF5F28711747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28811747CFA000502A6 = 6BF5F28811747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28911747CFA000502A6 = 6BF5F28911747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28A11747CFA000502A6 = 6BF5F28A11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28B11747CFA000502A6 = 6BF5F28B11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28C11747CFA000502A6 = 6BF5F28C11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28D11747CFA000502A6 = 6BF5F28D11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28E11747CFA000502A6 = 6BF5F28E11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F28F11747CFA000502A6 = 6BF5F28F11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F29011747CFA000502A6 = 6BF5F29011747CFA000502A6 /* PBXTextBookmark */; + 6BF5F29111747CFA000502A6 = 6BF5F29111747CFA000502A6 /* PBXTextBookmark */; + 6BF5F29B11747CFA000502A6 = 6BF5F29B11747CFA000502A6 /* PBXTextBookmark */; + 6BF5F2B111747E48000502A6 = 6BF5F2B111747E48000502A6 /* PBXTextBookmark */; + 6BF5F2B711747E6F000502A6 = 6BF5F2B711747E6F000502A6 /* PBXTextBookmark */; + 6BF5F2B811747E6F000502A6 = 6BF5F2B811747E6F000502A6 /* PBXTextBookmark */; + 6BF5F2E411748884000502A6 /* PBXTextBookmark */ = 6BF5F2E411748884000502A6 /* PBXTextBookmark */; + 6BF5F2E511748884000502A6 /* PBXTextBookmark */ = 6BF5F2E511748884000502A6 /* PBXTextBookmark */; + 6BF5F2E611748884000502A6 /* PBXTextBookmark */ = 6BF5F2E611748884000502A6 /* PBXTextBookmark */; + 6BF5F2E711748884000502A6 /* PBXTextBookmark */ = 6BF5F2E711748884000502A6 /* PBXTextBookmark */; + 6BF5F2E911748884000502A6 /* PBXTextBookmark */ = 6BF5F2E911748884000502A6 /* PBXTextBookmark */; + 6BF5F2EA11748884000502A6 /* PBXTextBookmark */ = 6BF5F2EA11748884000502A6 /* PBXTextBookmark */; + 6BF5F2EB11748884000502A6 /* PBXTextBookmark */ = 6BF5F2EB11748884000502A6 /* PBXTextBookmark */; + 6BF5F2EC11748884000502A6 /* PBXTextBookmark */ = 6BF5F2EC11748884000502A6 /* PBXTextBookmark */; + 6BF5F2ED11748884000502A6 /* PBXTextBookmark */ = 6BF5F2ED11748884000502A6 /* PBXTextBookmark */; + 6BF5F2EE11748884000502A6 /* PBXTextBookmark */ = 6BF5F2EE11748884000502A6 /* PBXTextBookmark */; + 6BF5F2EF11748884000502A6 /* PBXTextBookmark */ = 6BF5F2EF11748884000502A6 /* PBXTextBookmark */; + 6BF5F2F011748884000502A6 /* PBXTextBookmark */ = 6BF5F2F011748884000502A6 /* PBXTextBookmark */; + 6BF5F2F111748884000502A6 /* PBXTextBookmark */ = 6BF5F2F111748884000502A6 /* PBXTextBookmark */; + 6BF5F2F211748884000502A6 /* PBXTextBookmark */ = 6BF5F2F211748884000502A6 /* PBXTextBookmark */; + 6BF5F2F311748884000502A6 /* PBXTextBookmark */ = 6BF5F2F311748884000502A6 /* PBXTextBookmark */; + 6BF5F2F411748884000502A6 /* PBXTextBookmark */ = 6BF5F2F411748884000502A6 /* PBXTextBookmark */; + 6BF5F2F511748884000502A6 /* PBXTextBookmark */ = 6BF5F2F511748884000502A6 /* PBXTextBookmark */; + 6BF5F2F611748884000502A6 /* PBXTextBookmark */ = 6BF5F2F611748884000502A6 /* PBXTextBookmark */; + 6BF5F2F711748884000502A6 /* PBXTextBookmark */ = 6BF5F2F711748884000502A6 /* PBXTextBookmark */; + 6BF5F2F811748884000502A6 /* PBXTextBookmark */ = 6BF5F2F811748884000502A6 /* PBXTextBookmark */; + 6BF5F2F911748884000502A6 /* PBXTextBookmark */ = 6BF5F2F911748884000502A6 /* PBXTextBookmark */; + 6BF5F2FA11748884000502A6 /* PBXTextBookmark */ = 6BF5F2FA11748884000502A6 /* PBXTextBookmark */; + 6BF5F2FB11748884000502A6 /* PBXTextBookmark */ = 6BF5F2FB11748884000502A6 /* PBXTextBookmark */; + 6BF5F30511748884000502A6 /* PBXTextBookmark */ = 6BF5F30511748884000502A6 /* PBXTextBookmark */; }; sourceControlManager = 6B8632A90F78115100E2684A /* Source Control */; userBookmarkGroup = 6B8DE6F010A88F0500DF20FB /* PBXBookmarkGroup */; @@ -464,9 +417,10 @@ }; 6B137C830F7FCC1100459200 /* RecastContour.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {815, 12496}}"; - sepNavSelRange = "{15425, 0}"; - sepNavVisRange = "{15076, 681}"; + sepNavIntBoundsRect = "{{0, 0}, {909, 12864}}"; + sepNavSelRange = "{15251, 0}"; + sepNavVisRange = "{14919, 939}"; + sepNavWindowFrame = "{{38, 30}, {1214, 722}}"; }; }; 6B137C850F7FCC1100459200 /* RecastFilter.cpp */ = { @@ -528,9 +482,9 @@ }; 6B25B6180FFA62BE004F1BC4 /* main.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {815, 14832}}"; - sepNavSelRange = "{1099, 0}"; - sepNavVisRange = "{987, 420}"; + sepNavIntBoundsRect = "{{0, 0}, {909, 13536}}"; + sepNavSelRange = "{4446, 0}"; + sepNavVisRange = "{4083, 806}"; }; }; 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */ = { @@ -565,9 +519,9 @@ }; 6B555DAE100B211D00247EA3 /* imguiRenderGL.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {815, 416}}"; + sepNavIntBoundsRect = "{{0, 0}, {909, 532}}"; sepNavSelRange = "{446, 0}"; - sepNavVisRange = "{0, 1052}"; + sepNavVisRange = "{0, 1106}"; }; }; 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */ = { @@ -657,8 +611,8 @@ }; 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {909, 39872}}"; - sepNavSelRange = "{43934, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {909, 39632}}"; + sepNavSelRange = "{44054, 0}"; sepNavVisRange = "{43415, 1130}"; sepNavWindowFrame = "{{15, 51}, {1214, 722}}"; }; @@ -745,9 +699,9 @@ }; 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {936, 14688}}"; - sepNavSelRange = "{25264, 0}"; - sepNavVisRange = "{24647, 989}"; + sepNavIntBoundsRect = "{{0, 0}, {1195, 15296}}"; + sepNavSelRange = "{16316, 0}"; + sepNavVisRange = "{16266, 230}"; }; }; 6BB7FDA310F36EFC006DA0A6 /* InputGeom.h */ = { @@ -1011,16 +965,6 @@ vrLen = 312; vrLoc = 4961; }; - 6BBB4AA9115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B555DAE100B211D00247EA3 /* imguiRenderGL.h */; - name = "imguiRenderGL.h: 10"; - rLen = 0; - rLoc = 446; - rType = 0; - vrLen = 1052; - vrLoc = 0; - }; 6BBB4AAA115B4F3400CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B137C6C0F7FCBBB00459200 /* imgui.cpp */; @@ -1041,26 +985,6 @@ vrLen = 745; vrLoc = 1458; }; - 6BBB4AAC115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; - name = "main.cpp: 30"; - rLen = 0; - rLoc = 1099; - rType = 0; - vrLen = 420; - vrLoc = 987; - }; - 6BBB4AAF115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; - name = "OffMeshConnectionTool.cpp: 122"; - rLen = 0; - rLoc = 2934; - rType = 0; - vrLen = 449; - vrLoc = 2809; - }; 6BBB4AB0115B4F3400CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */; @@ -1331,36 +1255,6 @@ vrLen = 583; vrLoc = 5622; }; - 6BBB4AD5115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B1185FC10068B040018F96F /* DetourCommon.h */; - name = "DetourCommon.h: 1"; - rLen = 1062; - rLoc = 0; - rType = 0; - vrLen = 1063; - vrLoc = 0; - }; - 6BBB4AD6115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B1185FD10068B150018F96F /* DetourCommon.cpp */; - name = "DetourCommon.cpp: 226"; - rLen = 0; - rLoc = 5828; - rType = 0; - vrLen = 583; - vrLoc = 5622; - }; - 6BBB4AD7115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B1185FC10068B040018F96F /* DetourCommon.h */; - name = "DetourCommon.h: 5"; - rLen = 0; - rLoc = 148; - rType = 0; - vrLen = 1063; - vrLoc = 0; - }; 6BBB4AD8115B4F3400CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B1185F41006895B0018F96F /* DetourNode.cpp */; @@ -1371,26 +1265,6 @@ vrLen = 442; vrLoc = 1965; }; - 6BBB4AD9115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B1185F61006896B0018F96F /* DetourNode.h */; - name = "DetourNode.h: 5"; - rLen = 0; - rLoc = 151; - rType = 0; - vrLen = 986; - vrLoc = 0; - }; - 6BBB4ADB115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88C10B69E4C00DF20FB /* DetourNavMeshBuilder.h */; - name = "DetourNavMeshBuilder.h: 28"; - rLen = 0; - rLoc = 1125; - rType = 0; - vrLen = 607; - vrLoc = 987; - }; 6BBB4ADD115B4F3400CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BB93C7B10CFE1D500F74F2B /* DetourDebugDraw.cpp */; @@ -1476,7 +1350,7 @@ fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; name = "main.cpp: 40"; rLen = 0; - rLoc = 1353; + rLoc = 1333; rType = 0; vrLen = 420; vrLoc = 987; @@ -1601,26 +1475,6 @@ vrLen = 745; vrLoc = 1458; }; - 6BBB4AF2115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; - name = "main.cpp: 30"; - rLen = 0; - rLoc = 1099; - rType = 0; - vrLen = 420; - vrLoc = 987; - }; - 6BBB4AF3115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 705"; - rLen = 0; - rLoc = 18940; - rType = 0; - vrLen = 618; - vrLoc = 18789; - }; 6BBB4AF4115B4F3400CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; @@ -1631,26 +1485,6 @@ vrLen = 566; vrLoc = 1608; }; - 6BBB4AF5115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 705"; - rLen = 0; - rLoc = 18940; - rType = 0; - vrLen = 618; - vrLoc = 18789; - }; - 6BBB4AF6115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 63"; - rLen = 0; - rLoc = 1812; - rType = 0; - vrLen = 566; - vrLoc = 1608; - }; 6BBB4AF7115B4F3400CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; @@ -1911,26 +1745,6 @@ vrLen = 592; vrLoc = 21816; }; - 6BBB4B14115B4F3400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88C10B69E4C00DF20FB /* DetourNavMeshBuilder.h */; - name = "DetourNavMeshBuilder.h: 55"; - rLen = 0; - rLoc = 1802; - rType = 0; - vrLen = 793; - vrLoc = 1286; - }; - 6BBB4B2D115B5B3200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB93C7B10CFE1D500F74F2B /* DetourDebugDraw.cpp */; - name = "DetourDebugDraw.cpp: 120"; - rLen = 0; - rLoc = 3427; - rType = 0; - vrLen = 693; - vrLoc = 3273; - }; 6BBB4B3A115B5BFA00CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; @@ -1941,166 +1755,6 @@ vrLen = 1311; vrLoc = 7264; }; - 6BBB4B3C115B5BFA00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 198"; - rLen = 28; - rLoc = 8136; - rType = 0; - vrLen = 1258; - vrLoc = 7264; - }; - 6BBB4B41115B5D4B00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 199"; - rLen = 0; - rLoc = 8170; - rType = 0; - vrLen = 1513; - vrLoc = 6765; - }; - 6BBB4B43115B5D4B00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 199"; - rLen = 0; - rLoc = 8170; - rType = 0; - vrLen = 1468; - vrLoc = 6810; - }; - 6BBB4B45115B5D4B00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 438"; - rLen = 103; - rLoc = 19204; - rType = 0; - vrLen = 909; - vrLoc = 18110; - }; - 6BBB4B47115B5D4B00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 448"; - rLen = 0; - rLoc = 19564; - rType = 0; - vrLen = 958; - vrLoc = 18166; - }; - 6BBB4B49115B5D4B00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 452"; - rLen = 16; - rLoc = 19670; - rType = 0; - vrLen = 956; - vrLoc = 18166; - }; - 6BBB4B4E115B5DD900CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 509"; - rLen = 10; - rLoc = 22206; - rType = 0; - vrLen = 1395; - vrLoc = 20644; - }; - 6BBB4B5E115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 43"; - rLen = 0; - rLoc = 1700; - rType = 0; - vrLen = 1057; - vrLoc = 1080; - }; - 6BBB4B60115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 186"; - rLen = 0; - rLoc = 7375; - rType = 0; - vrLen = 1292; - vrLoc = 6328; - }; - 6BBB4B62115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 186"; - rLen = 0; - rLoc = 7375; - rType = 0; - vrLen = 1538; - vrLoc = 6810; - }; - 6BBB4B64115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 186"; - rLen = 0; - rLoc = 7375; - rType = 0; - vrLen = 1468; - vrLoc = 6810; - }; - 6BBB4B66115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 199"; - rLen = 9; - rLoc = 8083; - rType = 0; - vrLen = 1468; - vrLoc = 6810; - }; - 6BBB4B68115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 221"; - rLen = 0; - rLoc = 9084; - rType = 0; - vrLen = 1023; - vrLoc = 8160; - }; - 6BBB4B6A115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 221"; - rLen = 0; - rLoc = 9084; - rType = 0; - vrLen = 1023; - vrLoc = 8160; - }; - 6BBB4B6C115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 221"; - rLen = 54; - rLoc = 9084; - rType = 0; - vrLen = 1023; - vrLoc = 8160; - }; - 6BBB4B6E115B609F00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 220"; - rLen = 0; - rLoc = 9046; - rType = 0; - vrLen = 1023; - vrLoc = 8160; - }; 6BBB4B7A115B639200CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B8DE88810B69E3E00DF20FB /* DetourNavMeshBuilder.cpp */; @@ -2121,16 +1775,6 @@ vrLen = 388; vrLoc = 1188; }; - 6BBB4B7E115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 95"; - rLen = 41; - rLoc = 2994; - rType = 0; - vrLen = 393; - vrLoc = 2992; - }; 6BBB4B7F115B639200CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; @@ -2141,16 +1785,6 @@ vrLen = 674; vrLoc = 1608; }; - 6BBB4B85115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 54"; - rLen = 28; - rLoc = 1637; - rType = 0; - vrLen = 741; - vrLoc = 1467; - }; 6BBB4B87115B639200CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B8DE88810B69E3E00DF20FB /* DetourNavMeshBuilder.cpp */; @@ -2161,216 +1795,6 @@ vrLen = 698; vrLoc = 19240; }; - 6BBB4B88115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 142"; - rLen = 0; - rLoc = 5443; - rType = 0; - vrLen = 1408; - vrLoc = 4851; - }; - 6BBB4B8A115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 198"; - rLen = 0; - rLoc = 8100; - rType = 0; - vrLen = 1138; - vrLoc = 7379; - }; - 6BBB4B8C115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 198"; - rLen = 0; - rLoc = 8100; - rType = 0; - vrLen = 1138; - vrLoc = 7379; - }; - 6BBB4B8E115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 2"; - rLen = 0; - rLoc = 3; - rType = 0; - vrLen = 1067; - vrLoc = 0; - }; - 6BBB4B90115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 213"; - rLen = 9; - rLoc = 8697; - rType = 0; - vrLen = 879; - vrLoc = 7996; - }; - 6BBB4B92115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 220"; - rLen = 0; - rLoc = 8951; - rType = 0; - vrLen = 885; - vrLoc = 7996; - }; - 6BBB4B95115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 76"; - rLen = 17; - rLoc = 2155; - rType = 0; - vrLen = 599; - vrLoc = 1853; - }; - 6BBB4B96115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 108"; - rLen = 0; - rLoc = 3306; - rType = 0; - vrLen = 413; - vrLoc = 3101; - }; - 6BBB4B97115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 76"; - rLen = 17; - rLoc = 2155; - rType = 0; - vrLen = 496; - vrLoc = 1733; - }; - 6BBB4B98115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 105"; - rLen = 0; - rLoc = 3228; - rType = 0; - vrLen = 395; - vrLoc = 3101; - }; - 6BBB4B99115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 76"; - rLen = 17; - rLoc = 2155; - rType = 0; - vrLen = 496; - vrLoc = 1733; - }; - 6BBB4B9A115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 104"; - rLen = 0; - rLoc = 3205; - rType = 0; - vrLen = 413; - vrLoc = 3101; - }; - 6BBB4B9B115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 64"; - rLen = 19; - rLoc = 1834; - rType = 0; - vrLen = 496; - vrLoc = 1733; - }; - 6BBB4B9C115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 105"; - rLen = 0; - rLoc = 3206; - rType = 0; - vrLen = 393; - vrLoc = 2992; - }; - 6BBB4B9D115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 64"; - rLen = 19; - rLoc = 1834; - rType = 0; - vrLen = 496; - vrLoc = 1733; - }; - 6BBB4B9E115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 103"; - rLen = 0; - rLoc = 3184; - rType = 0; - vrLen = 393; - vrLoc = 2992; - }; - 6BBB4B9F115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8036AD113BAABE005ED67B /* Sample_Debug.cpp */; - name = "Sample_Debug.cpp: 38"; - rLen = 59; - rLoc = 1298; - rType = 0; - vrLen = 388; - vrLoc = 1188; - }; - 6BBB4BA0115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 95"; - rLen = 41; - rLoc = 2994; - rType = 0; - vrLen = 393; - vrLoc = 2992; - }; - 6BBB4BA1115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */; - name = "NavMeshTesterTool.h: 64"; - rLen = 0; - rLoc = 1852; - rType = 0; - vrLen = 674; - vrLoc = 1608; - }; - 6BBB4BA2115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 175"; - rLen = 0; - rLoc = 7024; - rType = 0; - vrLen = 1108; - vrLoc = 6517; - }; - 6BBB4BA3115B639200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BA1E88910C7BFC9008007F6 /* Sample_SoloMeshTiled.cpp */; - name = "Sample_SoloMeshTiled.cpp: 1098"; - rLen = 17; - rLoc = 32768; - rType = 0; - vrLen = 580; - vrLoc = 32356; - }; 6BBB4BAE115B649300CF791D /* Sample_TileMesh.cpp:552 */ = { isa = PBXFileBreakpoint; actions = ( @@ -2388,16 +1812,6 @@ modificationTime = 291208109.4759049; state = 1; }; - 6BBB4BB1115B649700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BA1E88810C7BFC9008007F6 /* Sample_SoloMeshSimple.cpp */; - name = "Sample_SoloMeshSimple.cpp: 580"; - rLen = 0; - rLoc = 17734; - rType = 0; - vrLen = 1146; - vrLoc = 16901; - }; 6BBB4BBE115B64E600CF791D /* Sample_TileMesh.cpp:585 */ = { isa = PBXFileBreakpoint; actions = ( @@ -2415,16 +1829,6 @@ modificationTime = 291208109.4762989; state = 1; }; - 6BBB4BCC115B653C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 439"; - rLen = 0; - rLoc = 19102; - rType = 0; - vrLen = 1282; - vrLoc = 17743; - }; 6BBB4BDA115B679300CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BA1E88910C7BFC9008007F6 /* Sample_SoloMeshTiled.cpp */; @@ -2435,36 +1839,6 @@ vrLen = 602; vrLoc = 32332; }; - 6BBB4BE0115B679300CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 43"; - rLen = 17; - rLoc = 1701; - rType = 0; - vrLen = 818; - vrLoc = 1042; - }; - 6BBB4BE1115B679300CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BA1E88910C7BFC9008007F6 /* Sample_SoloMeshTiled.cpp */; - name = "Sample_SoloMeshTiled.cpp: 1098"; - rLen = 0; - rLoc = 32785; - rType = 0; - vrLen = 602; - vrLoc = 32332; - }; - 6BBB4BE3115B679300CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 43"; - rLen = 17; - rLoc = 1701; - rType = 0; - vrLen = 818; - vrLoc = 1042; - }; 6BBB4BE6115B69BE00CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BA1E88810C7BFC9008007F6 /* Sample_SoloMeshSimple.cpp */; @@ -2475,246 +1849,6 @@ vrLen = 710; vrLoc = 18944; }; - 6BBB4BE8115B69BE00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BA1E88810C7BFC9008007F6 /* Sample_SoloMeshSimple.cpp */; - name = "Sample_SoloMeshSimple.cpp: 622"; - rLen = 0; - rLoc = 19192; - rType = 0; - vrLen = 710; - vrLoc = 18944; - }; - 6BBB4BED115B6B8A00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 256"; - rLen = 0; - rLoc = 10236; - rType = 0; - vrLen = 1218; - vrLoc = 9310; - }; - 6BBB4BEF115B6B8A00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 34"; - rLen = 0; - rLoc = 1333; - rType = 0; - vrLen = 775; - vrLoc = 923; - }; - 6BBB4BF1115B6B8A00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 34"; - rLen = 22; - rLoc = 1350; - rType = 0; - vrLen = 775; - vrLoc = 923; - }; - 6BBB4BF3115B6B8A00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 35"; - rLen = 24; - rLoc = 1436; - rType = 0; - vrLen = 775; - vrLoc = 923; - }; - 6BBB4BF5115B6B8A00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 81"; - rLen = 0; - rLoc = 3061; - rType = 0; - vrLen = 981; - vrLoc = 2528; - }; - 6BBB4BF7115B6B8A00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 82"; - rLen = 0; - rLoc = 3064; - rType = 0; - vrLen = 862; - vrLoc = 3461; - }; - 6BBB4BFF115B6D9C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 34"; - rLen = 22; - rLoc = 1350; - rType = 0; - vrLen = 846; - vrLoc = 1080; - }; - 6BBB4C01115B6D9C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 35"; - rLen = 24; - rLoc = 1436; - rType = 0; - vrLen = 846; - vrLoc = 1080; - }; - 6BBB4C03115B6D9C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 258"; - rLen = 0; - rLoc = 10144; - rType = 0; - vrLen = 1216; - vrLoc = 9500; - }; - 6BBB4C0A115B6E0200CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 252"; - rLen = 16; - rLoc = 9940; - rType = 0; - vrLen = 1688; - vrLoc = 9196; - }; - 6BBB4C10115B72F400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 58"; - rLen = 95; - rLoc = 1740; - rType = 0; - vrLen = 851; - vrLoc = 1424; - }; - 6BBB4C12115B72F400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 60"; - rLen = 0; - rLoc = 1835; - rType = 0; - vrLen = 852; - vrLoc = 1424; - }; - 6BBB4C17115B758400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 60"; - rLen = 0; - rLoc = 1835; - rType = 0; - vrLen = 852; - vrLoc = 1424; - }; - 6BBB4C18115B758400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 58"; - rLen = 0; - rLoc = 1740; - rType = 0; - vrLen = 875; - vrLoc = 1424; - }; - 6BBB4C19115B758400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 59"; - rLen = 10; - rLoc = 1797; - rType = 0; - vrLen = 865; - vrLoc = 1469; - }; - 6BBB4C1A115B758400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 58"; - rLen = 0; - rLoc = 1740; - rType = 0; - vrLen = 865; - vrLoc = 1469; - }; - 6BBB4C1B115B758400CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 59"; - rLen = 0; - rLoc = 1796; - rType = 0; - vrLen = 871; - vrLoc = 1469; - }; - 6BBB4C22115B784C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 180"; - rLen = 0; - rLoc = 6982; - rType = 0; - vrLen = 1151; - vrLoc = 6316; - }; - 6BBB4C24115B784C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 193"; - rLen = 43; - rLoc = 7503; - rType = 0; - vrLen = 1275; - vrLoc = 6777; - }; - 6BBB4C26115B784C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 527"; - rLen = 0; - rLoc = 21990; - rType = 0; - vrLen = 1537; - vrLoc = 21361; - }; - 6BBB4C28115B784C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 182"; - rLen = 0; - rLoc = 7026; - rType = 0; - vrLen = 1325; - vrLoc = 6777; - }; - 6BBB4C2A115B784C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 166"; - rLen = 0; - rLoc = 6740; - rType = 0; - vrLen = 1122; - vrLoc = 6063; - }; - 6BBB4C2C115B784C00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 167"; - rLen = 0; - rLoc = 6752; - rType = 0; - vrLen = 1122; - vrLoc = 6063; - }; 6BBB4C34115B7A3D00CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BBB4C35115B7A3D00CF791D /* string.h */; @@ -2759,36 +1893,6 @@ path = /Developer/SDKs/MacOSX10.5.sdk/usr/include/string.h; sourceTree = ""; }; - 6BBB4C3F115B7A3D00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 527"; - rLen = 0; - rLoc = 21990; - rType = 0; - vrLen = 1416; - vrLoc = 21293; - }; - 6BBB4C41115B7A3D00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 59"; - rLen = 0; - rLoc = 1826; - rType = 0; - vrLen = 731; - vrLoc = 1469; - }; - 6BBB4C43115B7A3D00CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */; - name = "Sample_TileMesh.h: 58"; - rLen = 0; - rLoc = 1760; - rType = 0; - vrLen = 713; - vrLoc = 1469; - }; 6BBB4C4C115B7BAD00CF791D /* Sample_TileMesh.cpp:263 */ = { isa = PBXFileBreakpoint; actions = ( @@ -2806,16 +1910,6 @@ modificationTime = 291208120.743975; state = 1; }; - 6BBB4C58115B8BF700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 581"; - rLen = 0; - rLoc = 15996; - rType = 0; - vrLen = 1210; - vrLoc = 15745; - }; 6BBB4C59115B8BF700CF791D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; @@ -2826,66 +1920,6 @@ vrLen = 1350; vrLoc = 3631; }; - 6BBB4C5A115B8BF700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */; - name = "Sample_TileMesh.cpp: 326"; - rLen = 0; - rLoc = 7109; - rType = 0; - vrLen = 903; - vrLoc = 6571; - }; - 6BBB4C5B115B8BF700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 527"; - rLen = 0; - rLoc = 21990; - rType = 0; - vrLen = 1680; - vrLoc = 21140; - }; - 6BBB4C5C115B8BF700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 581"; - rLen = 0; - rLoc = 15996; - rType = 0; - vrLen = 1210; - vrLoc = 15745; - }; - 6BBB4C5D115B8BF700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 527"; - rLen = 0; - rLoc = 21990; - rType = 0; - vrLen = 1680; - vrLoc = 21140; - }; - 6BBB4C5E115B8BF700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88B10B69E4C00DF20FB /* DetourNavMesh.h */; - name = "DetourNavMesh.h: 116"; - rLen = 0; - rLoc = 4182; - rType = 0; - vrLen = 1350; - vrLoc = 3631; - }; - 6BBB4C61115B906700CF791D /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */; - name = "Sample_TileMesh.cpp: 552"; - rLen = 0; - rLoc = 12702; - rType = 0; - vrLen = 887; - vrLoc = 12388; - }; 6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {815, 720}}"; @@ -2910,16 +1944,6 @@ vrLen = 887; vrLoc = 12388; }; - 6BED8AD51174509800582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 95"; - rLen = 41; - rLoc = 2994; - rType = 0; - vrLen = 611; - vrLoc = 2903; - }; 6BED8AD61174509800582F38 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */; @@ -2930,86 +1954,6 @@ vrLen = 887; vrLoc = 12388; }; - 6BED8AD71174509800582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 604"; - rLen = 0; - rLoc = 16316; - rType = 0; - vrLen = 953; - vrLoc = 15619; - }; - 6BED8AD81174509D00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 603"; - rLen = 0; - rLoc = 16316; - rType = 0; - vrLen = 400; - vrLoc = 16127; - }; - 6BED8ADB1174514E00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1665"; - rLen = 0; - rLoc = 45258; - rType = 0; - vrLen = 949; - vrLoc = 44471; - }; - 6BED8ADC1174514E00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 600"; - rLen = 16; - rLoc = 16160; - rType = 0; - vrLen = 1026; - vrLoc = 15665; - }; - 6BED8ADD1174514E00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 600"; - rLen = 16; - rLoc = 16160; - rType = 0; - vrLen = 970; - vrLoc = 15717; - }; - 6BED8ADE1174514E00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1665"; - rLen = 0; - rLoc = 45258; - rType = 0; - vrLen = 949; - vrLoc = 44471; - }; - 6BED8ADF1174514E00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 608"; - rLen = 0; - rLoc = 16316; - rType = 0; - vrLen = 1026; - vrLoc = 15665; - }; - 6BED8AE01174515300582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 608"; - rLen = 0; - rLoc = 16316; - rType = 0; - vrLen = 431; - vrLoc = 16081; - }; 6BED8AE2117451EB00582F38 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BB93C7B10CFE1D500F74F2B /* DetourDebugDraw.cpp */; @@ -3020,36 +1964,6 @@ vrLen = 815; vrLoc = 13539; }; - 6BED8AE3117451EB00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 870"; - rLen = 22; - rLoc = 24746; - rType = 0; - vrLen = 1001; - vrLoc = 24471; - }; - 6BED8AE4117451EB00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB93C7B10CFE1D500F74F2B /* DetourDebugDraw.cpp */; - name = "DetourDebugDraw.cpp: 481"; - rLen = 0; - rLoc = 14549; - rType = 0; - vrLen = 815; - vrLoc = 13539; - }; - 6BED8AE5117451EB00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; - name = "NavMeshTesterTool.cpp: 896"; - rLen = 0; - rLoc = 25264; - rType = 0; - vrLen = 951; - vrLoc = 24647; - }; 6BED8AEE117455CB00582F38 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; @@ -3060,16 +1974,6 @@ vrLen = 989; vrLoc = 24647; }; - 6BED8AEF117455CB00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1665"; - rLen = 0; - rLoc = 45258; - rType = 0; - vrLen = 949; - vrLoc = 44471; - }; 6BED8AF0117455CB00582F38 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; @@ -3080,16 +1984,6 @@ vrLen = 989; vrLoc = 24647; }; - 6BED8AF1117455CB00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1573"; - rLen = 0; - rLoc = 42169; - rType = 0; - vrLen = 998; - vrLoc = 41991; - }; 6BED8AF21174567000582F38 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; @@ -3100,46 +1994,691 @@ vrLen = 670; vrLoc = 2592; }; - 6BED8AF31174567000582F38 /* PBXTextBookmark */ = { + 6BF5F231117474CF000502A6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1573"; + name = "DetourNavMesh.cpp: 1635"; rLen = 0; - rLoc = 42169; - rType = 0; - vrLen = 998; - vrLoc = 41991; - }; - 6BED8AF41174567000582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; - name = "OffMeshConnectionTool.cpp: 120"; - rLen = 0; - rLoc = 2909; - rType = 0; - vrLen = 670; - vrLoc = 2592; - }; - 6BED8AF51174567000582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1675"; - rLen = 0; - rLoc = 45253; - rType = 0; - vrLen = 913; - vrLoc = 44814; - }; - 6BED8AF81174570F00582F38 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; - name = "DetourNavMesh.cpp: 1631"; - rLen = 0; - rLoc = 43934; + rLoc = 44054; rType = 0; vrLen = 1130; vrLoc = 43415; }; + 6BF5F233117474CF000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B8DE88710B69E3E00DF20FB /* DetourNavMesh.cpp */; + name = "DetourNavMesh.cpp: 1635"; + rLen = 0; + rLoc = 44054; + rType = 0; + vrLen = 1130; + vrLoc = 43415; + }; + 6BF5F23911747606000502A6 /* Filelist.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {909, 1600}}"; + sepNavSelRange = "{1296, 0}"; + sepNavVisRange = "{1035, 620}"; + }; + }; + 6BF5F23C11747614000502A6 /* Filelist.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {909, 576}}"; + sepNavSelRange = "{922, 0}"; + sepNavVisRange = "{64, 1116}"; + }; + }; + 6BF5F23E1174763B000502A6 /* SlideShow.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {909, 864}}"; + sepNavSelRange = "{1292, 0}"; + sepNavVisRange = "{920, 527}"; + }; + }; + 6BF5F23F1174763B000502A6 /* SlideShow.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {909, 2512}}"; + sepNavSelRange = "{2460, 0}"; + sepNavVisRange = "{2220, 739}"; + }; + }; + 6BF5F27011747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B555DAE100B211D00247EA3 /* imguiRenderGL.h */; + name = "imguiRenderGL.h: 10"; + rLen = 0; + rLoc = 446; + rType = 0; + vrLen = 1106; + vrLoc = 0; + }; + 6BF5F27111747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 32"; + rLen = 0; + rLoc = 1086; + rType = 0; + vrLen = 1177; + vrLoc = 3; + }; + 6BF5F27211747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; + name = "main.cpp: 21"; + rLen = 0; + rLoc = 986; + rType = 0; + vrLen = 1315; + vrLoc = 0; + }; + 6BF5F27311747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23911747606000502A6 /* Filelist.cpp */; + name = "Filelist.cpp: 38"; + rLen = 0; + rLoc = 1296; + rType = 0; + vrLen = 620; + vrLoc = 1035; + }; + 6BF5F27411747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 34"; + rLen = 0; + rLoc = 1123; + rType = 0; + vrLen = 489; + vrLoc = 920; + }; + 6BF5F27611747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B555DAE100B211D00247EA3 /* imguiRenderGL.h */; + name = "imguiRenderGL.h: 10"; + rLen = 0; + rLoc = 446; + rType = 0; + vrLen = 1106; + vrLoc = 0; + }; + 6BF5F27711747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 19"; + rLen = 0; + rLoc = 3983; + rType = 0; + vrLen = 924; + vrLoc = 0; + }; + 6BF5F27811747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 24"; + rLen = 0; + rLoc = 1180; + rType = 0; + vrLen = 985; + vrLoc = 0; + }; + 6BF5F27911747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; + name = "main.cpp: 46"; + rLen = 0; + rLoc = 1387; + rType = 0; + vrLen = 871; + vrLoc = 1112; + }; + 6BF5F27A11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 27"; + rLen = 0; + rLoc = 1047; + rType = 0; + vrLen = 1176; + vrLoc = 0; + }; + 6BF5F27B11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 27"; + rLen = 0; + rLoc = 1031; + rType = 0; + vrLen = 1159; + vrLoc = 0; + }; + 6BF5F27C11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 32"; + rLen = 0; + rLoc = 1086; + rType = 0; + vrLen = 1119; + vrLoc = 61; + }; + 6BF5F27D11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 32"; + rLen = 0; + rLoc = 1086; + rType = 0; + vrLen = 1177; + vrLoc = 3; + }; + 6BF5F27E11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 32"; + rLen = 0; + rLoc = 1086; + rType = 0; + vrLen = 1177; + vrLoc = 3; + }; + 6BF5F27F11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 32"; + rLen = 0; + rLoc = 1086; + rType = 0; + vrLen = 1177; + vrLoc = 3; + }; + 6BF5F28011747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23911747606000502A6 /* Filelist.cpp */; + name = "Filelist.cpp: 38"; + rLen = 0; + rLoc = 1296; + rType = 0; + vrLen = 620; + vrLoc = 1035; + }; + 6BF5F28111747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 19"; + rLen = 0; + rLoc = 924; + rType = 0; + vrLen = 1053; + vrLoc = 0; + }; + 6BF5F28211747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 29"; + rLen = 0; + rLoc = 2220; + rType = 0; + vrLen = 1048; + vrLoc = 0; + }; + 6BF5F28311747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 31"; + rLen = 0; + rLoc = 1212; + rType = 0; + vrLen = 742; + vrLoc = 521; + }; + 6BF5F28411747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 47"; + rLen = 0; + rLoc = 2220; + rType = 0; + vrLen = 420; + vrLoc = 923; + }; + 6BF5F28511747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 80"; + rLen = 0; + rLoc = 3983; + rType = 0; + vrLen = 873; + vrLoc = 1299; + }; + 6BF5F28611747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 73"; + rLen = 0; + rLoc = 2216; + rType = 0; + vrLen = 900; + vrLoc = 1346; + }; + 6BF5F28711747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 89"; + rLen = 0; + rLoc = 2220; + rType = 0; + vrLen = 911; + vrLoc = 1638; + }; + 6BF5F28811747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 80"; + rLen = 0; + rLoc = 2220; + rType = 0; + vrLen = 911; + vrLoc = 1638; + }; + 6BF5F28911747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 80"; + rLen = 0; + rLoc = 2220; + rType = 0; + vrLen = 911; + vrLoc = 1638; + }; + 6BF5F28A11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 81"; + rLen = 0; + rLoc = 2220; + rType = 0; + vrLen = 911; + vrLoc = 1638; + }; + 6BF5F28B11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 96"; + rLen = 0; + rLoc = 2786; + rType = 0; + vrLen = 745; + vrLoc = 2249; + }; + 6BF5F28C11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 103"; + rLen = 0; + rLoc = 3323; + rType = 0; + vrLen = 917; + vrLoc = 2005; + }; + 6BF5F28D11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 35"; + rLen = 0; + rLoc = 1153; + rType = 0; + vrLen = 829; + vrLoc = 446; + }; + 6BF5F28E11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 23"; + rLen = 0; + rLoc = 1065; + rType = 0; + vrLen = 544; + vrLoc = 672; + }; + 6BF5F28F11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 43"; + rLen = 0; + rLoc = 1275; + rType = 0; + vrLen = 486; + vrLoc = 923; + }; + 6BF5F29011747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 51"; + rLen = 0; + rLoc = 1403; + rType = 0; + vrLen = 811; + vrLoc = 1357; + }; + 6BF5F29111747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 34"; + rLen = 0; + rLoc = 1123; + rType = 0; + vrLen = 489; + vrLoc = 920; + }; + 6BF5F29B11747CFA000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F29C11747CFA000502A6 /* glimage.h */; + rLen = 0; + rLoc = 2147483647; + rType = 0; + }; + 6BF5F29C11747CFA000502A6 /* glimage.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = glimage.h; + path = /Users/memon/Code/recastnavigation/Backups/Backup_slideshow/Include/glimage.h; + sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1155, 594}}"; + sepNavSelRange = "{419, 71}"; + sepNavVisRange = "{0, 501}"; + }; + }; + 6BF5F2B111747E48000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + comments = "error: stb_image.c: No such file or directory"; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + rLen = 1; + rLoc = 23; + rType = 1; + }; + 6BF5F2B711747E6F000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 24"; + rLen = 0; + rLoc = 1064; + rType = 0; + vrLen = 690; + vrLoc = 596; + }; + 6BF5F2B811747E6F000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2B911747E6F000502A6 /* glimage.h */; + name = "glimage.h: 30"; + rLen = 71; + rLoc = 419; + rType = 0; + vrLen = 501; + vrLoc = 0; + }; + 6BF5F2B911747E6F000502A6 /* glimage.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = glimage.h; + path = /Users/memon/Code/recastnavigation/Backups/Backup_slideshow/Include/glimage.h; + sourceTree = ""; + }; + 6BF5F2C511747E9F000502A6 /* stb_image.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {971, 62304}}"; + sepNavSelRange = "{108151, 0}"; + sepNavVisRange = "{107791, 689}"; + }; + }; + 6BF5F2E411748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 17"; + rLen = 0; + rLoc = 922; + rType = 0; + vrLen = 1116; + vrLoc = 64; + }; + 6BF5F2E511748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2C511747E9F000502A6 /* stb_image.h */; + name = "stb_image.h: 3138"; + rLen = 0; + rLoc = 108151; + rType = 0; + vrLen = 689; + vrLoc = 107791; + }; + 6BF5F2E611748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 46"; + rLen = 0; + rLoc = 1292; + rType = 0; + vrLen = 527; + vrLoc = 920; + }; + 6BF5F2E711748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2E811748884000502A6 /* SDL_keysym.h */; + name = "SDL_keysym.h: 55"; + rLen = 11; + rLoc = 1666; + rType = 0; + vrLen = 660; + vrLoc = 1264; + }; + 6BF5F2E811748884000502A6 /* SDL_keysym.h */ = { + isa = PBXFileReference; + name = SDL_keysym.h; + path = /Library/Frameworks/SDL.framework/Versions/A/Headers/SDL_keysym.h; + sourceTree = ""; + }; + 6BF5F2E911748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B137C830F7FCC1100459200 /* RecastContour.cpp */; + name = "RecastContour.cpp: 596"; + rLen = 0; + rLoc = 15251; + rType = 0; + vrLen = 939; + vrLoc = 14919; + }; + 6BF5F2EA11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 97"; + rLen = 0; + rLoc = 2460; + rType = 0; + vrLen = 739; + vrLoc = 2220; + }; + 6BF5F2EB11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; + name = "main.cpp: 174"; + rLen = 0; + rLoc = 4347; + rType = 0; + vrLen = 880; + vrLoc = 4268; + }; + 6BF5F2EC11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23C11747614000502A6 /* Filelist.h */; + name = "Filelist.h: 17"; + rLen = 0; + rLoc = 922; + rType = 0; + vrLen = 1116; + vrLoc = 64; + }; + 6BF5F2ED11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2C511747E9F000502A6 /* stb_image.h */; + name = "stb_image.h: 423"; + rLen = 0; + rLoc = 18076; + rType = 0; + vrLen = 454; + vrLoc = 17844; + }; + 6BF5F2EE11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 27"; + rLen = 1; + rLoc = 1103; + rType = 0; + vrLen = 229; + vrLoc = 1010; + }; + 6BF5F2EF11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2C511747E9F000502A6 /* stb_image.h */; + name = "stb_image.h: 3858"; + rLen = 0; + rLoc = 127487; + rType = 0; + vrLen = 575; + vrLoc = 127073; + }; + 6BF5F2F011748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 33"; + rLen = 0; + rLoc = 1207; + rType = 0; + vrLen = 276; + vrLoc = 1010; + }; + 6BF5F2F111748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2C511747E9F000502A6 /* stb_image.h */; + name = "stb_image.h: 3138"; + rLen = 0; + rLoc = 108151; + rType = 0; + vrLen = 689; + vrLoc = 107791; + }; + 6BF5F2F211748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 31"; + rLen = 0; + rLoc = 1174; + rType = 0; + vrLen = 364; + vrLoc = 924; + }; + 6BF5F2F311748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F2C511747E9F000502A6 /* stb_image.h */; + name = "stb_image.h: 3138"; + rLen = 0; + rLoc = 108151; + rType = 0; + vrLen = 689; + vrLoc = 107791; + }; + 6BF5F2F411748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 46"; + rLen = 0; + rLoc = 1292; + rType = 0; + vrLen = 525; + vrLoc = 920; + }; + 6BF5F2F511748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 92"; + rLen = 0; + rLoc = 2660; + rType = 0; + vrLen = 953; + vrLoc = 1855; + }; + 6BF5F2F611748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23E1174763B000502A6 /* SlideShow.h */; + name = "SlideShow.h: 46"; + rLen = 0; + rLoc = 1292; + rType = 0; + vrLen = 527; + vrLoc = 920; + }; + 6BF5F2F711748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 101"; + rLen = 0; + rLoc = 2550; + rType = 0; + vrLen = 649; + vrLoc = 2201; + }; + 6BF5F2F811748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; + name = "main.cpp: 174"; + rLen = 0; + rLoc = 4347; + rType = 0; + vrLen = 880; + vrLoc = 4268; + }; + 6BF5F2F911748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B137C830F7FCC1100459200 /* RecastContour.cpp */; + name = "RecastContour.cpp: 596"; + rLen = 0; + rLoc = 15251; + rType = 0; + vrLen = 939; + vrLoc = 14919; + }; + 6BF5F2FA11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; + name = "SlideShow.cpp: 97"; + rLen = 0; + rLoc = 2460; + rType = 0; + vrLen = 739; + vrLoc = 2220; + }; + 6BF5F2FB11748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; + name = "main.cpp: 177"; + rLen = 0; + rLoc = 4446; + rType = 0; + vrLen = 806; + vrLoc = 4083; + }; + 6BF5F30511748884000502A6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 6BF5F29C11747CFA000502A6 /* glimage.h */; + name = "glimage.h: 30"; + rLen = 71; + rLoc = 419; + rType = 0; + vrLen = 501; + vrLoc = 0; + }; 6BF7C13E11119520002B3F46 /* TestCase.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {815, 1264}}"; diff --git a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3 b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3 index d61771e..30491d6 100644 --- a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3 +++ b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3 @@ -197,7 +197,48 @@ Notifications OpenEditors - + + + Content + + PBXProjectModuleGUID + 6BF5F29911747CFA000502A6 + PBXProjectModuleLabel + glimage.h + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 6BF5F29A11747CFA000502A6 + PBXProjectModuleLabel + glimage.h + _historyCapacity + 0 + bookmark + 6BF5F30511748884000502A6 + history + + 6BF5F2B811747E6F000502A6 + + + SplitCount + 1 + + StatusBarVisibility + + + Geometry + + Frame + {{0, 20}, {1214, 625}} + PBXModuleWindowStatusBarHidden2 + + RubberWindowFrame + 15 107 1214 666 0 0 1280 778 + + + PerspectiveWidths 1256 @@ -267,10 +308,7 @@ 29B97314FDCFA39411CA2CEA 080E96DDFE201D6D7F000001 - 6BB93C7610CFE1BD00F74F2B - 6BDD9E030F91110C00904EEF - 6B555DF5100B25FC00247EA3 - 6BB7FE8E10F4A175006DA0A6 + 6B137C7D0F7FCBE800459200 29B97315FDCFA39411CA2CEA 29B97317FDCFA39411CA2CEA 29B97323FDCFA39411CA2CEA @@ -282,14 +320,13 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 37 - 33 + 20 1 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 217}, {264, 643}} + {{0, 82}, {264, 643}} PBXTopSmartGroupGIDs @@ -324,7 +361,7 @@ PBXProjectModuleGUID 6B8632A30F78115100E2684A PBXProjectModuleLabel - DetourNavMesh.cpp + main.cpp PBXSplitModuleInNavigatorKey Split0 @@ -332,11 +369,11 @@ PBXProjectModuleGUID 6B8632A40F78115100E2684A PBXProjectModuleLabel - DetourNavMesh.cpp + main.cpp _historyCapacity 0 bookmark - 6BED8AF81174570F00582F38 + 6BF5F2FB11748884000502A6 history 6BBB4A94115B4F3400CF791D @@ -358,10 +395,8 @@ 6BBB4AA6115B4F3400CF791D 6BBB4AA7115B4F3400CF791D 6BBB4AA8115B4F3400CF791D - 6BBB4AA9115B4F3400CF791D 6BBB4AAA115B4F3400CF791D 6BBB4AAB115B4F3400CF791D - 6BBB4AAC115B4F3400CF791D 6BBB4AB0115B4F3400CF791D 6BBB4AB1115B4F3400CF791D 6BBB4AB2115B4F3400CF791D @@ -380,7 +415,6 @@ 6BBB4AC4115B4F3400CF791D 6BBB4AC5115B4F3400CF791D 6BBB4AC6115B4F3400CF791D - 6BBB4AC7115B4F3400CF791D 6BBB4AC8115B4F3400CF791D 6BBB4AC9115B4F3400CF791D 6BBB4ACB115B4F3400CF791D @@ -397,11 +431,16 @@ 6BED8AE2117451EB00582F38 6BED8AEE117455CB00582F38 6BED8AF21174567000582F38 - 6BED8AF31174567000582F38 - - nextStack - - 6BED8AF41174567000582F38 + 6BF5F231117474CF000502A6 + 6BF5F27011747CFA000502A6 + 6BF5F27311747CFA000502A6 + 6BF5F2E411748884000502A6 + 6BF5F2E511748884000502A6 + 6BF5F2E611748884000502A6 + 6BF5F2E711748884000502A6 + 6BF5F2E911748884000502A6 + 6BF5F2EA11748884000502A6 + 6BF5F2EB11748884000502A6 prevStack @@ -418,7 +457,6 @@ 6BBB4AE2115B4F3400CF791D 6BBB4AE3115B4F3400CF791D 6BBB4AE4115B4F3400CF791D - 6BBB4AE5115B4F3400CF791D 6BBB4AE6115B4F3400CF791D 6BBB4AE7115B4F3400CF791D 6BBB4AE8115B4F3400CF791D @@ -463,6 +501,25 @@ 6BBB4C3B115B7A3D00CF791D 6BED8AD61174509800582F38 6BED8AF0117455CB00582F38 + 6BF5F233117474CF000502A6 + 6BF5F27811747CFA000502A6 + 6BF5F28011747CFA000502A6 + 6BF5F28D11747CFA000502A6 + 6BF5F2EC11748884000502A6 + 6BF5F2ED11748884000502A6 + 6BF5F2EE11748884000502A6 + 6BF5F2EF11748884000502A6 + 6BF5F2F011748884000502A6 + 6BF5F2F111748884000502A6 + 6BF5F2F211748884000502A6 + 6BF5F2F311748884000502A6 + 6BF5F2F411748884000502A6 + 6BF5F2F511748884000502A6 + 6BF5F2F611748884000502A6 + 6BF5F2F711748884000502A6 + 6BF5F2F811748884000502A6 + 6BF5F2F911748884000502A6 + 6BF5F2FA11748884000502A6 SplitCount @@ -476,18 +533,18 @@ GeometryConfiguration Frame - {{0, 0}, {970, 564}} + {{0, 0}, {970, 578}} RubberWindowFrame 13 75 1256 702 0 0 1280 778 Module PBXNavigatorGroup Proportion - 564pt + 578pt Proportion - 92pt + 78pt Tabs @@ -501,9 +558,7 @@ GeometryConfiguration Frame - {{10, 27}, {970, 65}} - RubberWindowFrame - 13 75 1256 702 0 0 1280 778 + {{10, 27}, {970, 92}} Module XCDetailModule @@ -519,7 +574,7 @@ GeometryConfiguration Frame - {{10, 27}, {970, -27}} + {{10, 27}, {970, 287}} Module PBXProjectFindModule @@ -557,7 +612,9 @@ GeometryConfiguration Frame - {{10, 27}, {970, 65}} + {{10, 27}, {970, 51}} + RubberWindowFrame + 13 75 1256 702 0 0 1280 778 Module PBXBuildResultsModule @@ -585,11 +642,11 @@ TableOfContents - 6BED8AE6117451EB00582F38 + 6BF5F2FC11748884000502A6 1CA23ED40692098700951B8B - 6BED8AE7117451EB00582F38 + 6BF5F2FD11748884000502A6 6B8632A30F78115100E2684A - 6BED8AE8117451EB00582F38 + 6BF5F2FE11748884000502A6 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -738,14 +795,14 @@ TableOfContents - 6BED8AE9117451EB00582F38 + 6BF5F2FF11748884000502A6 1CCC7628064C1048000F2A68 1CCC7629064C1048000F2A68 - 6BED8AEA117451EB00582F38 - 6BED8AEB117451EB00582F38 - 6BED8AEC117451EB00582F38 - 6BED8AED117451EB00582F38 - 6B8632A30F78115100E2684A + 6BF5F30011748884000502A6 + 6BF5F30111748884000502A6 + 6BF5F30211748884000502A6 + 6BF5F30311748884000502A6 + 6BF5F30411748884000502A6 ToolbarConfigUserDefaultsMinorVersion 2 @@ -777,6 +834,7 @@ 5 WindowOrderList + 6BF5F29911747CFA000502A6 /Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj WindowString diff --git a/RecastDemo/Build/Xcode/Recast.xcodeproj/project.pbxproj b/RecastDemo/Build/Xcode/Recast.xcodeproj/project.pbxproj index d9da79f..bed94e1 100644 --- a/RecastDemo/Build/Xcode/Recast.xcodeproj/project.pbxproj +++ b/RecastDemo/Build/Xcode/Recast.xcodeproj/project.pbxproj @@ -43,6 +43,8 @@ 6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */; }; 6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; }; 6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; }; + 6BF5F23A11747606000502A6 /* Filelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23911747606000502A6 /* Filelist.cpp */; }; + 6BF5F2401174763B000502A6 /* SlideShow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; }; 6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C13F1111953A002B3F46 /* TestCase.cpp */; }; 6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C4531115C277002B3F46 /* RecastArea.cpp */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; @@ -118,6 +120,11 @@ 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastDump.cpp; path = ../../../DebugUtils/Source/RecastDump.cpp; sourceTree = SOURCE_ROOT; }; 6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OffMeshConnectionTool.h; path = ../../Include/OffMeshConnectionTool.h; sourceTree = SOURCE_ROOT; }; 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; }; + 6BF5F23911747606000502A6 /* Filelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Filelist.cpp; path = ../../Source/Filelist.cpp; sourceTree = SOURCE_ROOT; }; + 6BF5F23C11747614000502A6 /* Filelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Filelist.h; path = ../../Include/Filelist.h; sourceTree = SOURCE_ROOT; }; + 6BF5F23E1174763B000502A6 /* SlideShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SlideShow.h; path = ../../Include/SlideShow.h; sourceTree = SOURCE_ROOT; }; + 6BF5F23F1174763B000502A6 /* SlideShow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SlideShow.cpp; path = ../../Source/SlideShow.cpp; sourceTree = SOURCE_ROOT; }; + 6BF5F2C511747E9F000502A6 /* stb_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_image.h; path = ../../Contrib/stb_image.h; sourceTree = SOURCE_ROOT; }; 6BF7C13E11119520002B3F46 /* TestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestCase.h; path = ../../Include/TestCase.h; sourceTree = SOURCE_ROOT; }; 6BF7C13F1111953A002B3F46 /* TestCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestCase.cpp; path = ../../Source/TestCase.cpp; sourceTree = SOURCE_ROOT; }; 6BF7C4531115C277002B3F46 /* RecastArea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastArea.cpp; path = ../../../Recast/Source/RecastArea.cpp; sourceTree = SOURCE_ROOT; }; @@ -142,13 +149,18 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( - 6B555DF6100B273500247EA3 /* stb_truetype.h */, 6BB93C7610CFE1BD00F74F2B /* DebugUtils */, 6BDD9E030F91110C00904EEF /* Detour */, 6B137C7D0F7FCBE800459200 /* Recast */, 6B555DF5100B25FC00247EA3 /* Samples */, 6BB7FE8E10F4A175006DA0A6 /* Tools */, 6B25B6180FFA62BE004F1BC4 /* main.cpp */, + 6BF5F2C511747E9F000502A6 /* stb_image.h */, + 6BF5F23E1174763B000502A6 /* SlideShow.h */, + 6BF5F23F1174763B000502A6 /* SlideShow.cpp */, + 6BF5F23C11747614000502A6 /* Filelist.h */, + 6BF5F23911747606000502A6 /* Filelist.cpp */, + 6B555DF6100B273500247EA3 /* stb_truetype.h */, 6B137C7A0F7FCBE400459200 /* imgui.h */, 6B137C6C0F7FCBBB00459200 /* imgui.cpp */, 6B555DAE100B211D00247EA3 /* imguiRenderGL.h */, @@ -405,6 +417,8 @@ 6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */, 6B324C66111C5D9A00EBD2FD /* ConvexVolumeTool.cpp in Sources */, 6B8036AE113BAABE005ED67B /* Sample_Debug.cpp in Sources */, + 6BF5F23A11747606000502A6 /* Filelist.cpp in Sources */, + 6BF5F2401174763B000502A6 /* SlideShow.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -453,6 +467,7 @@ "-Wall", ); PRODUCT_NAME = Recast; + USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; }; @@ -478,6 +493,7 @@ "-Wall", ); PRODUCT_NAME = Recast; + USER_HEADER_SEARCH_PATHS = ""; }; name = Release; }; diff --git a/RecastDemo/Contrib/stb_image.h b/RecastDemo/Contrib/stb_image.h new file mode 100644 index 0000000..404819f --- /dev/null +++ b/RecastDemo/Contrib/stb_image.h @@ -0,0 +1,3893 @@ +/* stbi-1.18 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c + when you control the images you're loading + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline (no JPEG progressive, no oddball channel decimations) + PNG 8-bit only + BMP non-1bpp, non-RLE + TGA (not sure what subset, if a subset) + PSD (composited view only, no extra channels) + HDR (radiance rgbE format) + writes BMP,TGA (define STBI_NO_WRITE to remove code) + decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code) + supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) + + TODO: + stbi_info_* + + history: + 1.18 fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less + than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant +*/ + + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +//// begin header file //////////////////////////////////////////////////// +// +// Limitations: +// - no progressive/interlaced support (jpeg, png) +// - 8-bit samples only (jpeg, png) +// - not threadsafe +// - channel subsampling of at most 2 in each dimension (jpeg) +// - no delayed line count (jpeg) -- IJG doesn't support either +// +// Basic usage (see HDR discussion below): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to easily see if it's opaque. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG and BMP images are automatically depalettized. +// +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); + +#ifndef STBI_NO_STDIO +#include +#endif + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4, +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +// WRITING API + +#if !defined(STBI_NO_WRITE) && !defined(STBI_NO_STDIO) +// write a BMP/TGA file given tightly packed 'comp' channels (no padding, nor bmp-stride-padding) +// (you must include the appropriate extension in the filename). +// returns TRUE on success, FALSE if couldn't open file, error writing file +extern int stbi_write_bmp (char const *filename, int x, int y, int comp, void *data); +extern int stbi_write_tga (char const *filename, int x, int y, int comp, void *data); +#endif + +// PRIMARY API - works on images of any type + +// load image by filename, open file, or memory buffer +#ifndef STBI_NO_STDIO +extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +// for stbi_load_from_file, file pointer is left pointing immediately after image + +#ifndef STBI_NO_HDR +#ifndef STBI_NO_STDIO +extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); +extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +#endif +extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + +extern void stbi_hdr_to_ldr_gamma(float gamma); +extern void stbi_hdr_to_ldr_scale(float scale); + +extern void stbi_ldr_to_hdr_gamma(float gamma); +extern void stbi_ldr_to_hdr_scale(float scale); + +#endif // STBI_NO_HDR + +// get a VERY brief reason for failure +// NOT THREADSAFE +extern const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +extern void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +extern int stbi_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_is_hdr (char const *filename); +extern int stbi_is_hdr_from_file(FILE *f); +#endif + +// ZLIB client - used by PNG, available for other purposes + +extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +// TYPE-SPECIFIC ACCESS + +// is it a jpeg? +extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len); +extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern int stbi_jpeg_test_file (FILE *f); +extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif + +// is it a png? +extern int stbi_png_test_memory (stbi_uc const *buffer, int len); +extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern int stbi_png_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_png_test_file (FILE *f); +extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif + +// is it a bmp? +extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len); + +extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +#ifndef STBI_NO_STDIO +extern int stbi_bmp_test_file (FILE *f); +extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +#endif + +// is it a tga? +extern int stbi_tga_test_memory (stbi_uc const *buffer, int len); + +extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +#ifndef STBI_NO_STDIO +extern int stbi_tga_test_file (FILE *f); +extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +#endif + +// is it a psd? +extern int stbi_psd_test_memory (stbi_uc const *buffer, int len); + +extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +#ifndef STBI_NO_STDIO +extern int stbi_psd_test_file (FILE *f); +extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +#endif + +// is it an hdr? +extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len); + +extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +#ifndef STBI_NO_STDIO +extern int stbi_hdr_test_file (FILE *f); +extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +#endif + +// define new loaders +typedef struct +{ + int (*test_memory)(stbi_uc const *buffer, int len); + stbi_uc * (*load_from_memory)(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + #ifndef STBI_NO_STDIO + int (*test_file)(FILE *f); + stbi_uc * (*load_from_file)(FILE *f, int *x, int *y, int *comp, int req_comp); + #endif +} stbi_loader; + +// register a loader by filling out the above structure (you must defined ALL functions) +// returns 1 if added or already added, 0 if not added (too many loaders) +// NOT THREADSAFE +extern int stbi_register_loader(stbi_loader *loader); + +// define faster low-level operations (typically SIMD support) +#if STBI_SIMD +typedef void (*stbi_idct_8x8)(uint8 *out, int out_stride, short data[64], unsigned short *dequantize); +// compute an integer IDCT on "input" +// input[x] = data[x] * dequantize[x] +// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride' +// CLAMP results to 0..255 +typedef void (*stbi_YCbCr_to_RGB_run)(uint8 *output, uint8 const *y, uint8 const *cb, uint8 const *cr, int count, int step); +// compute a conversion from YCbCr to RGB +// 'count' pixels +// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B +// y: Y input channel +// cb: Cb input channel; scale/biased to be 0..255 +// cr: Cr input channel; scale/biased to be 0..255 + +extern void stbi_install_idct(stbi_idct_8x8 func); +extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); +#endif // STBI_SIMD + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifndef STBI_HEADER_FILE_ONLY + +#ifndef STBI_NO_HDR +#include // ldexp +#include // strcmp +#endif + +#ifndef STBI_NO_STDIO +#include +#endif +#include +#include +#include +#include + +#ifndef _MSC_VER + #ifdef __cplusplus + #define __forceinline inline + #else + #define __forceinline + #endif +#endif + + +// implementation: +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned int uint; + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(uint32)==4]; + +#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE) +#define STBI_NO_WRITE +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Generic API that works on all image types +// + +// this is not threadsafe +static const char *failure_reason; + +const char *stbi_failure_reason(void) +{ + return failure_reason; +} + +static int e(const char *str) +{ + failure_reason = str; + return 0; +} + +#ifdef STBI_NO_FAILURE_STRINGS + #define e(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define e(x,y) e(y) +#else + #define e(x,y) e(x) +#endif + +#define epf(x,y) ((float *) (e(x,y)?NULL:NULL)) +#define epuc(x,y) ((unsigned char *) (e(x,y)?NULL:NULL)) + +void stbi_image_free(void *retval_from_stbi_load) +{ + free(retval_from_stbi_load); +} + +#define MAX_LOADERS 32 +stbi_loader *loaders[MAX_LOADERS]; +static int max_loaders = 0; + +int stbi_register_loader(stbi_loader *loader) +{ + int i; + for (i=0; i < MAX_LOADERS; ++i) { + // already present? + if (loaders[i] == loader) + return 1; + // end of the list? + if (loaders[i] == NULL) { + loaders[i] = loader; + max_loaders = i+1; + return 1; + } + } + // no room for it + return 0; +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_STDIO +unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + unsigned char *result; + if (!f) return epuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + int i; + if (stbi_jpeg_test_file(f)) + return stbi_jpeg_load_from_file(f,x,y,comp,req_comp); + if (stbi_png_test_file(f)) + return stbi_png_load_from_file(f,x,y,comp,req_comp); + if (stbi_bmp_test_file(f)) + return stbi_bmp_load_from_file(f,x,y,comp,req_comp); + if (stbi_psd_test_file(f)) + return stbi_psd_load_from_file(f,x,y,comp,req_comp); + #ifndef STBI_NO_HDR + if (stbi_hdr_test_file(f)) { + float *hdr = stbi_hdr_load_from_file(f, x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + for (i=0; i < max_loaders; ++i) + if (loaders[i]->test_file(f)) + return loaders[i]->load_from_file(f,x,y,comp,req_comp); + // test tga last because it's a crappy test! + if (stbi_tga_test_file(f)) + return stbi_tga_load_from_file(f,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} +#endif + +unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + int i; + if (stbi_jpeg_test_memory(buffer,len)) + return stbi_jpeg_load_from_memory(buffer,len,x,y,comp,req_comp); + if (stbi_png_test_memory(buffer,len)) + return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp); + if (stbi_bmp_test_memory(buffer,len)) + return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp); + if (stbi_psd_test_memory(buffer,len)) + return stbi_psd_load_from_memory(buffer,len,x,y,comp,req_comp); + #ifndef STBI_NO_HDR + if (stbi_hdr_test_memory(buffer, len)) { + float *hdr = stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + for (i=0; i < max_loaders; ++i) + if (loaders[i]->test_memory(buffer,len)) + return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp); + // test tga last because it's a crappy test! + if (stbi_tga_test_memory(buffer,len)) + return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_HDR + +#ifndef STBI_NO_STDIO +float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + float *result; + if (!f) return epf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test_file(f)) + return stbi_hdr_load_from_file(f,x,y,comp,req_comp); + #endif + data = stbi_load_from_file(f, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} +#endif + +float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test_memory(buffer, len)) + return stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); + #endif + data = stbi_load_from_memory(buffer, len, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} +#endif + +// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is +// defined, for API simplicity; if STBI_NO_HDR is defined, it always +// reports false! + +int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + return stbi_hdr_test_memory(buffer, len); + #else + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +extern int stbi_is_hdr (char const *filename) +{ + FILE *f = fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +extern int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + return stbi_hdr_test_file(f); + #else + return 0; + #endif +} + +#endif + +// @TODO: get image dimensions & components without fully decoding +#ifndef STBI_NO_STDIO +extern int stbi_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +#ifndef STBI_NO_HDR +static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f; +static float l2h_gamma=2.2f, l2h_scale=1.0f; + +void stbi_hdr_to_ldr_gamma(float gamma) { h2l_gamma_i = 1/gamma; } +void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; } + +void stbi_ldr_to_hdr_gamma(float gamma) { l2h_gamma = gamma; } +void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; } +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + SCAN_load=0, + SCAN_type, + SCAN_header, +}; + +typedef struct +{ + uint32 img_x, img_y; + int img_n, img_out_n; + + #ifndef STBI_NO_STDIO + FILE *img_file; + #endif + uint8 *img_buffer, *img_buffer_end; +} stbi; + +#ifndef STBI_NO_STDIO +static void start_file(stbi *s, FILE *f) +{ + s->img_file = f; + s->img_buffer = NULL; + s->img_buffer_end = NULL; +} +#endif + +static void start_mem(stbi *s, uint8 const *buffer, int len) +{ +#ifndef STBI_NO_STDIO + s->img_file = NULL; +#endif + s->img_buffer = (uint8 *) buffer; + s->img_buffer_end = (uint8 *) buffer+len; +} + +__forceinline static int get8(stbi *s) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) { + int c = fgetc(s->img_file); + return c == EOF ? 0 : c; + } +#endif + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + return 0; +} + +__forceinline static int at_eof(stbi *s) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) + return feof(s->img_file); +#endif + return s->img_buffer >= s->img_buffer_end; +} + +__forceinline static uint8 get8u(stbi *s) +{ + return (uint8) get8(s); +} + +static void skip(stbi *s, int n) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) + fseek(s->img_file, n, SEEK_CUR); + else +#endif + s->img_buffer += n; +} + +static int get16(stbi *s) +{ + int z = get8(s); + return (z << 8) + get8(s); +} + +static uint32 get32(stbi *s) +{ + uint32 z = get16(s); + return (z << 16) + get16(s); +} + +static int get16le(stbi *s) +{ + int z = get8(s); + return z + (get8(s) << 8); +} + +static uint32 get32le(stbi *s) +{ + uint32 z = get16le(s); + return z + (get16le(s) << 16); +} + +static void getn(stbi *s, stbi_uc *buffer, int n) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) { + fread(buffer, 1, n, s->img_file); + return; + } +#endif + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; +} + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static uint8 compute_y(int r, int g, int b) +{ + return (uint8) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + assert(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) malloc(req_comp * x * y); + if (good == NULL) { + free(data); + return epuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch(COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: assert(0); + } + #undef CASE + } + + free(data); + return good; +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) malloc(x * y * comp * sizeof(float)); + if (output == NULL) { free(data); return epf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) pow(data[i*comp+k]/255.0f, l2h_gamma) * l2h_scale; + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + free(data); + return output; +} + +#define float2int(x) ((int) (x)) +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) malloc(x * y * comp); + if (output == NULL) { free(data); return epuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = float2int(z); + } + } + free(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation) +// +// simple implementation +// - channel subsampling of at most 2 in each dimension +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - uses a lot of intermediate memory, could cache poorly +// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4 +// stb_jpeg: 1.34 seconds (MSVC6, default release build) +// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro) +// IJL11.dll: 1.08 seconds (compiled by intel) +// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG) +// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro) + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + uint8 fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + uint16 code[256]; + uint8 values[256]; + uint8 size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} huffman; + +typedef struct +{ + #if STBI_SIMD + unsigned short dequant2[4][64]; + #endif + stbi s; + huffman huff_dc[4]; + huffman huff_ac[4]; + uint8 dequant[4][64]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + uint8 *data; + void *raw_data; + uint8 *linebuf; + } img_comp[4]; + + uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int scan_n, order[4]; + int restart_interval, todo; +} jpeg; + +static int build_huffman(huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (uint8) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (uint16) (code++); + if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (uint8) i; + } + } + } + return 1; +} + +static void grow_buffer_unsafe(jpeg *j) +{ + do { + int b = j->nomore ? 0 : get8(&j->s); + if (b == 0xff) { + int c = get8(&j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer = (j->code_buffer << 8) | b; + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +__forceinline static int decode(jpeg *j, huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (j->code_bits - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + if (h->size[k] > j->code_bits) + return -1; + j->code_bits -= h->size[k]; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + if (j->code_bits < 16) + temp = (j->code_buffer << (16 - j->code_bits)) & 0xffff; + else + temp = (j->code_buffer >> (j->code_bits - 16)) & 0xffff; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (j->code_bits - k)) & bmask[k]) + h->delta[k]; + assert((((j->code_buffer) >> (j->code_bits - h->size[c])) & bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + return h->values[c]; +} + +// combined JPEG 'receive' and JPEG 'extend', since baseline +// always extends everything it receives. +__forceinline static int extend_receive(jpeg *j, int n) +{ + unsigned int m = 1 << (n-1); + unsigned int k; + if (j->code_bits < n) grow_buffer_unsafe(j); + k = (j->code_buffer >> (j->code_bits - n)) & bmask[n]; + j->code_bits -= n; + // the following test is probably a random branch that won't + // predict well. I tried to table accelerate it but failed. + // maybe it's compiling as a conditional move? + if (k < m) + return (-1 << n) + k + 1; + else + return k; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static uint8 dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int b) +{ + int diff,dc,k; + int t = decode(j, hdc); + if (t < 0) return e("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) dc; + + // decode AC components, see JPEG spec + k = 1; + do { + int r,s; + int rs = decode(j, hac); + if (rs < 0) return e("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + data[dezigzag[k++]] = (short) extend_receive(j,s); + } + } while (k < 64); + return 1; +} + +// take a -128..127 value and clamp it and convert to 0..255 +__forceinline static uint8 clamp(int x) +{ + x += 128; + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (uint8) x; +} + +#define f2f(x) (int) (((x) * 4096 + 0.5)) +#define fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * f2f(0.5411961f); \ + t2 = p1 + p3*f2f(-1.847759065f); \ + t3 = p1 + p2*f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = fsh(p2+p3); \ + t1 = fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*f2f( 1.175875602f); \ + t0 = t0*f2f( 0.298631336f); \ + t1 = t1*f2f( 2.053119869f); \ + t2 = t2*f2f( 3.072711026f); \ + t3 = t3*f2f( 1.501321110f); \ + p1 = p5 + p1*f2f(-0.899976223f); \ + p2 = p5 + p2*f2f(-2.562915447f); \ + p3 = p3*f2f(-1.961570560f); \ + p4 = p4*f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +#if !STBI_SIMD +// .344 seconds on 3*anemones.jpg +static void idct_block(uint8 *out, int out_stride, short data[64], uint8 *dequantize) +{ + int i,val[64],*v=val; + uint8 *o,*dq = dequantize; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536; + o[0] = clamp((x0+t3) >> 17); + o[7] = clamp((x0-t3) >> 17); + o[1] = clamp((x1+t2) >> 17); + o[6] = clamp((x1-t2) >> 17); + o[2] = clamp((x2+t1) >> 17); + o[5] = clamp((x2-t1) >> 17); + o[3] = clamp((x3+t0) >> 17); + o[4] = clamp((x3-t0) >> 17); + } +} +#else +static void idct_block(uint8 *out, int out_stride, short data[64], unsigned short *dequantize) +{ + int i,val[64],*v=val; + uint8 *o; + unsigned short *dq = dequantize; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536; + o[0] = clamp((x0+t3) >> 17); + o[7] = clamp((x0-t3) >> 17); + o[1] = clamp((x1+t2) >> 17); + o[6] = clamp((x1-t2) >> 17); + o[2] = clamp((x2+t1) >> 17); + o[5] = clamp((x2-t1) >> 17); + o[3] = clamp((x3+t0) >> 17); + o[4] = clamp((x3-t0) >> 17); + } +} +static stbi_idct_8x8 stbi_idct_installed = idct_block; + +extern void stbi_install_idct(stbi_idct_8x8 func) +{ + stbi_idct_installed = func; +} +#endif + +#define MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static uint8 get_marker(jpeg *j) +{ + uint8 x; + if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; } + x = get8u(&j->s); + if (x != 0xff) return MARKER_none; + while (x == 0xff) + x = get8u(&j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, reset the entropy decoder and +// the dc prediction +static void reset(jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int parse_entropy_coded_data(jpeg *z) +{ + reset(z); + if (z->scan_n == 1) { + int i,j; + #if STBI_SIMD + __declspec(align(16)) + #endif + short data[64]; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #if STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } else { // interleaved! + int i,j,k,x,y; + short data[64]; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #if STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } + return 1; +} + +static int process_marker(jpeg *z, int m) +{ + int L; + switch (m) { + case MARKER_none: // no marker found + return e("expected marker","Corrupt JPEG"); + + case 0xC2: // SOF - progressive + return e("progressive jpeg","JPEG format not supported (progressive)"); + + case 0xDD: // DRI - specify restart interval + if (get16(&z->s) != 4) return e("bad DRI len","Corrupt JPEG"); + z->restart_interval = get16(&z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = get16(&z->s)-2; + while (L > 0) { + int q = get8(&z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return e("bad DQT type","Corrupt JPEG"); + if (t > 3) return e("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][dezigzag[i]] = get8u(&z->s); + #if STBI_SIMD + for (i=0; i < 64; ++i) + z->dequant2[t][i] = z->dequant[t][i]; + #endif + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = get16(&z->s)-2; + while (L > 0) { + uint8 *v; + int sizes[16],i,m=0; + int q = get8(&z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = get8(&z->s); + m += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < m; ++i) + v[i] = get8u(&z->s); + L -= m; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + skip(&z->s, get16(&z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int process_scan_header(jpeg *z) +{ + int i; + int Ls = get16(&z->s); + z->scan_n = get8(&z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s.img_n) return e("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = get8(&z->s), which; + int q = get8(&z->s); + for (which = 0; which < z->s.img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s.img_n) return 0; + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); + get8(&z->s); // should be 63, but might be 0 + if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); + + return 1; +} + +static int process_frame_header(jpeg *z, int scan) +{ + stbi *s = &z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG + p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = get16(s); if (s->img_y == 0) return e("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = get16(s); if (s->img_x == 0) return e("0 width","Corrupt JPEG"); // JPEG requires + c = get8(s); + if (c != 3 && c != 1) return e("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return e("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return e("bad component ID","Corrupt JPEG"); + q = get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return e("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return e("bad V","Corrupt JPEG"); + z->img_comp[i].tq = get8(s); if (z->img_comp[i].tq > 3) return e("bad TQ","Corrupt JPEG"); + } + + if (scan != SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + free(z->img_comp[i].raw_data); + z->img_comp[i].data = NULL; + } + return e("outofmem", "Out of memory"); + } + // align blocks for installable-idct using mmx/sse + z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define DNL(x) ((x) == 0xdc) +#define SOI(x) ((x) == 0xd8) +#define EOI(x) ((x) == 0xd9) +#define SOF(x) ((x) == 0xc0 || (x) == 0xc1) +#define SOS(x) ((x) == 0xda) + +static int decode_jpeg_header(jpeg *z, int scan) +{ + int m; + z->marker = MARKER_none; // initialize cached marker to empty + m = get_marker(z); + if (!SOI(m)) return e("no SOI","Corrupt JPEG"); + if (scan == SCAN_type) return 1; + m = get_marker(z); + while (!SOF(m)) { + if (!process_marker(z,m)) return 0; + m = get_marker(z); + while (m == MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (at_eof(&z->s)) return e("no SOF", "Corrupt JPEG"); + m = get_marker(z); + } + } + if (!process_frame_header(z, scan)) return 0; + return 1; +} + +static int decode_jpeg_image(jpeg *j) +{ + int m; + j->restart_interval = 0; + if (!decode_jpeg_header(j, SCAN_load)) return 0; + m = get_marker(j); + while (!EOI(m)) { + if (SOS(m)) { + if (!process_scan_header(j)) return 0; + if (!parse_entropy_coded_data(j)) return 0; + } else { + if (!process_marker(j, m)) return 0; + } + m = get_marker(j); + } + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, + int w, int hs); + +#define div4(x) ((uint8) ((x) >> 2)) + +static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + return in_near; +} + +static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + for (i=0; i < w; ++i) + out[i] = div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + uint8 *input = in_near; + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = div4(n+input[i-1]); + out[i*2+1] = div4(n+input[i+1]); + } + out[i*2+0] = div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + return out; +} + +#define div16(x) ((uint8) ((x) >> 4)) + +static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = div16(3*t0 + t1 + 8); + out[i*2 ] = div16(3*t1 + t0 + 8); + } + out[w*2-1] = div4(t1+2); + return out; +} + +static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) + +// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) +// VC6 without processor=Pro is generating multiple LEAs per multiply! +static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (uint8)r; + out[1] = (uint8)g; + out[2] = (uint8)b; + out[3] = 255; + out += step; + } +} + +#if STBI_SIMD +static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; + +void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) +{ + stbi_YCbCr_installed = func; +} +#endif + + +// clean up the temporary component buffers +static void cleanup_jpeg(jpeg *j) +{ + int i; + for (i=0; i < j->s.img_n; ++i) { + if (j->img_comp[i].data) { + free(j->img_comp[i].raw_data); + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].linebuf) { + free(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + uint8 *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi_resample; + +static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + // validate req_comp + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + z->s.img_n = 0; + + // load a jpeg image from whichever source + if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s.img_n; + + if (z->s.img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s.img_n; + + // resample and color-convert + { + int k; + uint i,j; + uint8 *output; + uint8 *coutput[4]; + + stbi_resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (uint8 *) malloc(z->s.img_x + 3); + if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s.img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = resample_row_hv_2; + else r->resample = resample_row_generic; + } + + // can't error after this so, this is safe + output = (uint8 *) malloc(n * z->s.img_x * z->s.img_y + 1); + if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s.img_y; ++j) { + uint8 *out = output + n * z->s.img_x * j; + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + uint8 *y = coutput[0]; + if (z->s.img_n == 3) { + #if STBI_SIMD + stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); + #else + YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s.img_x, n); + #endif + } else + for (i=0; i < z->s.img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + uint8 *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s.img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s.img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + cleanup_jpeg(z); + *out_x = z->s.img_x; + *out_y = z->s.img_y; + if (comp) *comp = z->s.img_n; // report original components, not output + return output; + } +} + +#ifndef STBI_NO_STDIO +unsigned char *stbi_jpeg_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + jpeg j; + start_file(&j.s, f); + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +unsigned char *stbi_jpeg_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_jpeg_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return data; +} +#endif + +unsigned char *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + jpeg j; + start_mem(&j.s, buffer,len); + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +int stbi_jpeg_test_file(FILE *f) +{ + int n,r; + jpeg j; + n = ftell(f); + start_file(&j.s, f); + r = decode_jpeg_header(&j, SCAN_type); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_jpeg_test_memory(stbi_uc const *buffer, int len) +{ + jpeg j; + start_mem(&j.s, buffer,len); + return decode_jpeg_header(&j, SCAN_type); +} + +// @TODO: +#ifndef STBI_NO_STDIO +extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define ZFAST_BITS 9 // accelerate all cases in default tables +#define ZFAST_MASK ((1 << ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + uint16 fast[1 << ZFAST_BITS]; + uint16 firstcode[16]; + int maxcode[17]; + uint16 firstsymbol[16]; + uint8 size[288]; + uint16 value[288]; +} zhuffman; + +__forceinline static int bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +__forceinline static int bit_reverse(int v, int bits) +{ + assert(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return bitreverse16(v) >> (16-bits); +} + +static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 255, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + assert(sizes[i] <= (1 << i)); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (uint16) code; + z->firstsymbol[i] = (uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return e("bad codelengths","Corrupt JPEG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + z->size[c] = (uint8)s; + z->value[c] = (uint16)i; + if (s <= ZFAST_BITS) { + int k = bit_reverse(next_code[s],s); + while (k < (1 << ZFAST_BITS)) { + z->fast[k] = (uint16) c; + k += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + uint8 *zbuffer, *zbuffer_end; + int num_bits; + uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + zhuffman z_length, z_distance; +} zbuf; + +__forceinline static int zget8(zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void fill_bits(zbuf *z) +{ + do { + assert(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +__forceinline static unsigned int zreceive(zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +__forceinline static int zhuffman_decode(zbuf *a, zhuffman *z) +{ + int b,s,k; + if (a->num_bits < 16) fill_bits(a); + b = z->fast[a->code_buffer & ZFAST_MASK]; + if (b < 0xffff) { + s = z->size[b]; + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; + } + + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = bit_reverse(a->code_buffer, 16); + for (s=ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + assert(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +static int expand(zbuf *z, int n) // need to make room for n bytes +{ + char *q; + int cur, limit; + if (!z->z_expandable) return e("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) realloc(z->zout_start, limit); + if (q == NULL) return e("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int length_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int length_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int dist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int parse_huffman_block(zbuf *a) +{ + for(;;) { + int z = zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return e("bad huffman code","Corrupt PNG"); // error in huffman codes + if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0; + *a->zout++ = (char) z; + } else { + uint8 *p; + int len,dist; + if (z == 256) return 1; + z -= 257; + len = length_base[z]; + if (length_extra[z]) len += zreceive(a, length_extra[z]); + z = zhuffman_decode(a, &a->z_distance); + if (z < 0) return e("bad huffman code","Corrupt PNG"); + dist = dist_base[z]; + if (dist_extra[z]) dist += zreceive(a, dist_extra[z]); + if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG"); + if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0; + p = (uint8 *) (a->zout - dist); + while (len--) + *a->zout++ = *p++; + } + } +} + +static int compute_huffman_codes(zbuf *a) +{ + static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + zhuffman z_codelength; + uint8 lencodes[286+32+137];//padding for maximum single op + uint8 codelength_sizes[19]; + int i,n; + + int hlit = zreceive(a,5) + 257; + int hdist = zreceive(a,5) + 1; + int hclen = zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (uint8) s; + } + if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = zhuffman_decode(a, &z_codelength); + assert(c >= 0 && c < 19); + if (c < 16) + lencodes[n++] = (uint8) c; + else if (c == 16) { + c = zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + assert(c == 18); + c = zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return e("bad codelengths","Corrupt PNG"); + if (!zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int parse_uncompressed_block(zbuf *a) +{ + uint8 header[4]; + int len,nlen,k; + if (a->num_bits & 7) + zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns? + a->code_buffer >>= 8; + a->num_bits -= 8; + } + assert(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = (uint8) zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return e("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!expand(a, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int parse_zlib_header(zbuf *a) +{ + int cmf = zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = zget8(a); + if ((cmf*256+flg) % 31 != 0) return e("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return e("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return e("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static uint8 default_length[288], default_distance[32]; +static void init_defaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) default_length[i] = 8; + for ( ; i <= 255; ++i) default_length[i] = 9; + for ( ; i <= 279; ++i) default_length[i] = 7; + for ( ; i <= 287; ++i) default_length[i] = 8; + + for (i=0; i <= 31; ++i) default_distance[i] = 5; +} + +int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead +static int parse_zlib(zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = zreceive(a,1); + type = zreceive(a,2); + if (type == 0) { + if (!parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!default_distance[31]) init_defaults(); + if (!zbuild_huffman(&a->z_length , default_length , 288)) return 0; + if (!zbuild_huffman(&a->z_distance, default_distance, 32)) return 0; + } else { + if (!compute_huffman_codes(a)) return 0; + } + if (!parse_huffman_block(a)) return 0; + } + if (stbi_png_partial && a->zout - a->zout_start > 65536) + break; + } while (!final); + return 1; +} + +static int do_zlib(zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return parse_zlib(a, parse_header); +} + +char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer + len; + if (do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer+len; + if (do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + + +typedef struct +{ + uint32 length; + uint32 type; +} chunk; + +#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static chunk get_chunk_header(stbi *s) +{ + chunk c; + c.length = get32(s); + c.type = get32(s); + return c; +} + +static int check_png_header(stbi *s) +{ + static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (get8(s) != png_sig[i]) return e("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi s; + uint8 *idata, *expanded, *out; +} png; + + +enum { + F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4, + F_avg_first, F_paeth_first, +}; + +static uint8 first_row_filter[5] = +{ + F_none, F_sub, F_none, F_avg_first, F_paeth_first +}; + +static int paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +// create the png data from post-deflated data +static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y) +{ + stbi *s = &a->s; + uint32 i,j,stride = x*out_n; + int k; + int img_n = s->img_n; // copy it into a local for later + assert(out_n == s->img_n || out_n == s->img_n+1); + if (stbi_png_partial) y = 1; + a->out = (uint8 *) malloc(x * y * out_n); + if (!a->out) return e("outofmem", "Out of memory"); + if (!stbi_png_partial) { + if (s->img_x == x && s->img_y == y) + if (raw_len != (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + else // interlaced: + if (raw_len < (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } + for (j=0; j < y; ++j) { + uint8 *cur = a->out + stride*j; + uint8 *prior = cur - stride; + int filter = *raw++; + if (filter > 4) return e("invalid filter","Corrupt PNG"); + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + // handle first pixel explicitly + for (k=0; k < img_n; ++k) { + switch(filter) { + case F_none : cur[k] = raw[k]; break; + case F_sub : cur[k] = raw[k]; break; + case F_up : cur[k] = raw[k] + prior[k]; break; + case F_avg : cur[k] = raw[k] + (prior[k]>>1); break; + case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break; + case F_avg_first : cur[k] = raw[k]; break; + case F_paeth_first: cur[k] = raw[k]; break; + } + } + if (img_n != out_n) cur[img_n] = 255; + raw += img_n; + cur += out_n; + prior += out_n; + // this is a little gross, so that we don't switch per-pixel or per-component + if (img_n == out_n) { + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \ + for (k=0; k < img_n; ++k) + switch(filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; + } + #undef CASE + } else { + assert(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch(filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + return 1; +} + +static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced) +{ + uint8 *final; + int p; + int save; + if (!interlaced) + return create_png_image_raw(a, raw, raw_len, out_n, a->s.img_x, a->s.img_y); + save = stbi_png_partial; + stbi_png_partial = 0; + + // de-interlacing + final = (uint8 *) malloc(a->s.img_x * a->s.img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s.img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s.img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) { + free(final); + return 0; + } + for (j=0; j < y; ++j) + for (i=0; i < x; ++i) + memcpy(final + (j*yspc[p]+yorig[p])*a->s.img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + a->out + (j*x+i)*out_n, out_n); + free(a->out); + raw += (x*out_n+1)*y; + raw_len -= (x*out_n+1)*y; + } + } + a->out = final; + + stbi_png_partial = save; + return 1; +} + +static int compute_transparency(png *z, uint8 tc[3], int out_n) +{ + stbi *s = &z->s; + uint32 i, pixel_count = s->img_x * s->img_y; + uint8 *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + assert(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) +{ + uint32 i, pixel_count = a->s.img_x * a->s.img_y; + uint8 *p, *temp_out, *orig = a->out; + + p = (uint8 *) malloc(pixel_count * pal_img_n); + if (p == NULL) return e("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + free(a->out); + a->out = temp_out; + return 1; +} + +static int parse_png_file(png *z, int scan, int req_comp) +{ + uint8 palette[1024], pal_img_n=0; + uint8 has_trans=0, tc[3]; + uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0; + stbi *s = &z->s; + + if (!check_png_header(s)) return 0; + + if (scan == SCAN_type) return 1; + + for(;;first=0) { + chunk c = get_chunk_header(s); + if (first && c.type != PNG_TYPE('I','H','D','R')) + return e("first not IHDR","Corrupt PNG"); + switch (c.type) { + case PNG_TYPE('I','H','D','R'): { + int depth,color,comp,filter; + if (!first) return e("multiple IHDR","Corrupt PNG"); + if (c.length != 13) return e("bad IHDR len","Corrupt PNG"); + s->img_x = get32(s); if (s->img_x > (1 << 24)) return e("too large","Very large image (corrupt?)"); + s->img_y = get32(s); if (s->img_y > (1 << 24)) return e("too large","Very large image (corrupt?)"); + depth = get8(s); if (depth != 8) return e("8bit only","PNG not supported: 8-bit only"); + color = get8(s); if (color > 6) return e("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return e("bad ctype","Corrupt PNG"); + comp = get8(s); if (comp) return e("bad comp method","Corrupt PNG"); + filter= get8(s); if (filter) return e("bad filter method","Corrupt PNG"); + interlace = get8(s); if (interlace>1) return e("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return e("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + if (scan == SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return e("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case PNG_TYPE('P','L','T','E'): { + if (c.length > 256*3) return e("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return e("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = get8u(s); + palette[i*4+1] = get8u(s); + palette[i*4+2] = get8u(s); + palette[i*4+3] = 255; + } + break; + } + + case PNG_TYPE('t','R','N','S'): { + if (z->idata) return e("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = get8u(s); + } else { + if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG"); + if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (uint8) get16(s); // non 8-bit images will be larger + } + break; + } + + case PNG_TYPE('I','D','A','T'): { + if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG"); + if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } + if (ioff + c.length > idata_limit) { + uint8 *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); + z->idata = p; + } + #ifndef STBI_NO_STDIO + if (s->img_file) + { + if (fread(z->idata+ioff,1,c.length,s->img_file) != c.length) return e("outofdata","Corrupt PNG"); + } + else + #endif + { + memcpy(z->idata+ioff, s->img_buffer, c.length); + s->img_buffer += c.length; + } + ioff += c.length; + break; + } + + case PNG_TYPE('I','E','N','D'): { + uint32 raw_len; + if (scan != SCAN_load) return 1; + if (z->idata == NULL) return e("no IDAT","Corrupt PNG"); + z->expanded = (uint8 *) stbi_zlib_decode_malloc((char *) z->idata, ioff, (int *) &raw_len); + if (z->expanded == NULL) return 0; // zlib should set error + free(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0; + if (has_trans) + if (!compute_transparency(z, tc, s->img_out_n)) return 0; + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!expand_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + free(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX chunk not known"; + invalid_chunk[0] = (uint8) (c.type >> 24); + invalid_chunk[1] = (uint8) (c.type >> 16); + invalid_chunk[2] = (uint8) (c.type >> 8); + invalid_chunk[3] = (uint8) (c.type >> 0); + #endif + return e(invalid_chunk, "PNG not supported: unknown chunk type"); + } + skip(s, c.length); + break; + } + // end of chunk, read and skip CRC + get32(s); + } +} + +static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + p->expanded = NULL; + p->idata = NULL; + p->out = NULL; + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + if (parse_png_file(p, SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s.img_out_n) { + result = convert_format(result, p->s.img_out_n, req_comp, p->s.img_x, p->s.img_y); + p->s.img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s.img_x; + *y = p->s.img_y; + if (n) *n = p->s.img_n; + } + free(p->out); p->out = NULL; + free(p->expanded); p->expanded = NULL; + free(p->idata); p->idata = NULL; + + return result; +} + +#ifndef STBI_NO_STDIO +unsigned char *stbi_png_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + png p; + start_file(&p.s, f); + return do_png(&p, x,y,comp,req_comp); +} + +unsigned char *stbi_png_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_png_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return data; +} +#endif + +unsigned char *stbi_png_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + png p; + start_mem(&p.s, buffer,len); + return do_png(&p, x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +int stbi_png_test_file(FILE *f) +{ + png p; + int n,r; + n = ftell(f); + start_file(&p.s, f); + r = parse_png_file(&p, SCAN_type,STBI_default); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_png_test_memory(stbi_uc const *buffer, int len) +{ + png p; + start_mem(&p.s, buffer, len); + return parse_png_file(&p, SCAN_type,STBI_default); +} + +// TODO: load header from png +#ifndef STBI_NO_STDIO +int stbi_png_info (char const *filename, int *x, int *y, int *comp) +{ + png p; + FILE *f = fopen(filename, "rb"); + if (!f) return 0; + start_file(&p.s, f); + if (parse_png_file(&p, SCAN_header, 0)) { + if(x) *x = p.s.img_x; + if(y) *y = p.s.img_y; + if (comp) *comp = p.s.img_n; + fclose(f); + return 1; + } + fclose(f); + return 0; +} + +extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +// Microsoft/Windows BMP image + +static int bmp_test(stbi *s) +{ + int sz; + if (get8(s) != 'B') return 0; + if (get8(s) != 'M') return 0; + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + get32le(s); // discard data offset + sz = get32le(s); + if (sz == 12 || sz == 40 || sz == 56 || sz == 108) return 1; + return 0; +} + +#ifndef STBI_NO_STDIO +int stbi_bmp_test_file (FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s,f); + r = bmp_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_bmp_test_memory (stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return bmp_test(&s); +} + +// returns 0..31 for the highest set bit +static int high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + uint8 *out; + unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; + stbi_uc pal[256][4]; + int psize=0,i,j,compress=0,width; + int bpp, flip_vertically, pad, target, offset, hsz; + if (get8(s) != 'B' || get8(s) != 'M') return epuc("not BMP", "Corrupt BMP"); + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + offset = get32le(s); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return epuc("unknown BMP", "BMP type not supported: unknown"); + failure_reason = "bad BMP"; + if (hsz == 12) { + s->img_x = get16le(s); + s->img_y = get16le(s); + } else { + s->img_x = get32le(s); + s->img_y = get32le(s); + } + if (get16le(s) != 1) return 0; + bpp = get16le(s); + if (bpp == 1) return epuc("monochrome", "BMP type not supported: 1-bit"); + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + if (hsz == 12) { + if (bpp < 24) + psize = (offset - 14 - 24) / 3; + } else { + compress = get32le(s); + if (compress == 1 || compress == 2) return epuc("BMP RLE", "BMP type not supported: RLE"); + get32le(s); // discard sizeof + get32le(s); // discard hres + get32le(s); // discard vres + get32le(s); // discard colorsused + get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + get32le(s); + get32le(s); + get32le(s); + get32le(s); + } + if (bpp == 16 || bpp == 32) { + mr = mg = mb = 0; + if (compress == 0) { + if (bpp == 32) { + mr = 0xff << 16; + mg = 0xff << 8; + mb = 0xff << 0; + ma = 0xff << 24; + fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 + } else { + mr = 31 << 10; + mg = 31 << 5; + mb = 31 << 0; + } + } else if (compress == 3) { + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (mr == mg && mg == mb) { + // ?!?!? + return NULL; + } + } else + return NULL; + } + } else { + assert(hsz == 108); + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + ma = get32le(s); + get32le(s); // discard color space + for (i=0; i < 12; ++i) + get32le(s); // discard color space parameters + } + if (bpp < 16) + psize = (offset - 14 - hsz) >> 2; + } + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + out = (stbi_uc *) malloc(target * s->img_x * s->img_y); + if (!out) return epuc("outofmem", "Out of memory"); + if (bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { free(out); return epuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = get8(s); + pal[i][1] = get8(s); + pal[i][0] = get8(s); + if (hsz != 12) get8(s); + pal[i][3] = 255; + } + skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); + if (bpp == 4) width = (s->img_x + 1) >> 1; + else if (bpp == 8) width = s->img_x; + else { free(out); return epuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=get8(s),v2=0; + if (bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (bpp == 8) ? get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + skip(s, offset - 14 - hsz); + if (bpp == 24) width = 3 * s->img_x; + else if (bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (bpp == 24) { + easy = 1; + } else if (bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0xff000000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) return epuc("bad masks", "Corrupt BMP"); + // right shift amt to put high bit in position #7 + rshift = high_bit(mr)-7; rcount = bitcount(mr); + gshift = high_bit(mg)-7; gcount = bitcount(mr); + bshift = high_bit(mb)-7; bcount = bitcount(mr); + ashift = high_bit(ma)-7; acount = bitcount(mr); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + int a; + out[z+2] = get8(s); + out[z+1] = get8(s); + out[z+0] = get8(s); + z += 3; + a = (easy == 2 ? get8(s) : 255); + if (target == 4) out[z++] = a; + } + } else { + for (i=0; i < (int) s->img_x; ++i) { + uint32 v = (bpp == 16 ? get16le(s) : get32le(s)); + int a; + out[z++] = shiftsigned(v & mr, rshift, rcount); + out[z++] = shiftsigned(v & mg, gshift, gcount); + out[z++] = shiftsigned(v & mb, bshift, bcount); + a = (ma ? shiftsigned(v & ma, ashift, acount) : 255); + if (target == 4) out[z++] = a; + } + } + skip(s, pad); + } + } + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = target; + return out; +} + +#ifndef STBI_NO_STDIO +stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_bmp_load_from_file(f, x,y,comp,req_comp); + fclose(f); + return data; +} + +stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s, f); + return bmp_load(&s, x,y,comp,req_comp); +} +#endif + +stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s, buffer, len); + return bmp_load(&s, x,y,comp,req_comp); +} + +// Targa Truevision - TGA +// by Jonathan Dummer + +static int tga_test(stbi *s) +{ + int sz; + get8u(s); // discard Offset + sz = get8u(s); // color type + if( sz > 1 ) return 0; // only RGB or indexed allowed + sz = get8u(s); // image type + if( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE + get16(s); // discard palette start + get16(s); // discard palette length + get8(s); // discard bits per palette color entry + get16(s); // discard x origin + get16(s); // discard y origin + if( get16(s) < 1 ) return 0; // test width + if( get16(s) < 1 ) return 0; // test height + sz = get8(s); // bits per pixel + if( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) return 0; // only RGB or RGBA or grey allowed + return 1; // seems to have passed everything +} + +#ifndef STBI_NO_STDIO +int stbi_tga_test_file (FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s, f); + r = tga_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_tga_test_memory (stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return tga_test(&s); +} + +static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = get8u(s); + int tga_indexed = get8u(s); + int tga_image_type = get8u(s); + int tga_is_RLE = 0; + int tga_palette_start = get16le(s); + int tga_palette_len = get16le(s); + int tga_palette_bits = get8u(s); + int tga_x_origin = get16le(s); + int tga_y_origin = get16le(s); + int tga_width = get16le(s); + int tga_height = get16le(s); + int tga_bits_per_pixel = get8u(s); + int tga_inverted = get8u(s); + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0,0,0,0}; + unsigned char trans_data[4] = {0,0,0,0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + // do a tiny bit of precessing + if( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + /* int tga_alpha_bits = tga_inverted & 15; */ + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // error check + if( //(tga_indexed) || + (tga_width < 1) || (tga_height < 1) || + (tga_image_type < 1) || (tga_image_type > 3) || + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) + ) + { + return NULL; + } + + // If I'm paletted, then I'll use the number of bits from the palette + if( tga_indexed ) + { + tga_bits_per_pixel = tga_palette_bits; + } + + // tga info + *x = tga_width; + *y = tga_height; + if( (req_comp < 1) || (req_comp > 4) ) + { + // just use whatever the file was + req_comp = tga_bits_per_pixel / 8; + *comp = req_comp; + } else + { + // force a new number of components + *comp = tga_bits_per_pixel/8; + } + tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp ); + + // skip to the data's starting position (offset usually = 0) + skip(s, tga_offset ); + // do I need to load a palette? + if( tga_indexed ) + { + // any data to skip? (offset usually = 0) + skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); + getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 ); + } + // load the data + for( i = 0; i < tga_width * tga_height; ++i ) + { + // if I'm in RLE mode, do I need to get a RLE chunk? + if( tga_is_RLE ) + { + if( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = get8u(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if( read_next_pixel ) + { + // load however much data we did have + if( tga_indexed ) + { + // read in 1 byte, then perform the lookup + int pal_idx = get8u(s); + if( pal_idx >= tga_palette_len ) + { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_bits_per_pixel / 8; + for( j = 0; j*8 < tga_bits_per_pixel; ++j ) + { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else + { + // read in the data raw + for( j = 0; j*8 < tga_bits_per_pixel; ++j ) + { + raw_data[j] = get8u(s); + } + } + // convert raw to the intermediate format + switch( tga_bits_per_pixel ) + { + case 8: + // Luminous => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 16: + // Luminous,Alpha => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[1]; + break; + case 24: + // BGR => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 32: + // BGRA => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[3]; + break; + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + // convert to final format + switch( req_comp ) + { + case 1: + // RGBA => Luminance + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + break; + case 2: + // RGBA => Luminance,Alpha + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + tga_data[i*req_comp+1] = trans_data[3]; + break; + case 3: + // RGBA => RGB + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + break; + case 4: + // RGBA => RGBA + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + tga_data[i*req_comp+3] = trans_data[3]; + break; + } + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if( tga_inverted ) + { + for( j = 0; j*2 < tga_height; ++j ) + { + int index1 = j * tga_width * req_comp; + int index2 = (tga_height - 1 - j) * tga_width * req_comp; + for( i = tga_width * req_comp; i > 0; --i ) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if( tga_palette != NULL ) + { + free( tga_palette ); + } + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} + +#ifndef STBI_NO_STDIO +stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_tga_load_from_file(f, x,y,comp,req_comp); + fclose(f); + return data; +} + +stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s, f); + return tga_load(&s, x,y,comp,req_comp); +} +#endif + +stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s, buffer, len); + return tga_load(&s, x,y,comp,req_comp); +} + + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicholas Schulz, tweaked by STB + +static int psd_test(stbi *s) +{ + if (get32(s) != 0x38425053) return 0; // "8BPS" + else return 1; +} + +#ifndef STBI_NO_STDIO +int stbi_psd_test_file(FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s, f); + r = psd_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_psd_test_memory(stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return psd_test(&s); +} + +static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int w,h; + uint8 *out; + + // Check identifier + if (get32(s) != 0x38425053) // "8BPS" + return epuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (get16(s) != 1) + return epuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) + return epuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = get32(s); + w = get32(s); + + // Make sure the depth is 8 bits. + if (get16(s) != 8) + return epuc("unsupported bit depth", "PSD bit depth is not 8 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (get16(s) != 3) + return epuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + skip(s,get32(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + skip(s, get32(s) ); + + // Skip the reserved data. + skip(s, get32(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = get16(s); + if (compression > 1) + return epuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) malloc(4 * w*h); + if (!out) return epuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = get8(s); + p += 4; + len--; + } + } else if (len > 128) { + uint32 val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out + channel; + if (channel > channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; + } else { + // Read the data. + count = 0; + for (i = 0; i < pixelCount; i++) + *p = get8(s), p += 4; + } + } + } + + if (req_comp && req_comp != 4) { + out = convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // convert_format frees input on failure + } + + if (comp) *comp = channelCount; + *y = h; + *x = w; + + return out; +} + +#ifndef STBI_NO_STDIO +stbi_uc *stbi_psd_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_psd_load_from_file(f, x,y,comp,req_comp); + fclose(f); + return data; +} + +stbi_uc *stbi_psd_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s, f); + return psd_load(&s, x,y,comp,req_comp); +} +#endif + +stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s, buffer, len); + return psd_load(&s, x,y,comp,req_comp); +} + + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int hdr_test(stbi *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (get8(s) != signature[i]) + return 0; + return 1; +} + +int stbi_hdr_test_memory(stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return hdr_test(&s); +} + +#ifndef STBI_NO_STDIO +int stbi_hdr_test_file(FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s, f); + r = hdr_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +#define HDR_BUFLEN 1024 +static char *hdr_gettoken(stbi *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = get8(z); + + while (!at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == HDR_BUFLEN-1) { + // flush to end of line + while (!at_eof(z) && get8(z) != '\n') + ; + break; + } + c = get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + + +static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return epf("not HDR", "Corrupt HDR image"); + + // Parse header + while(1) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return epf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = strtol(token, NULL, 10); + + *x = width; + *y = height; + + *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + getn(s, rgbe, 4); + hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = get8(s); + c2 = get8(s); + len = get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4] = { c1,c2,len, get8(s) }; + hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + free(scanline); + goto main_decode_loop; // yes, this is fucking insane; blame the fucking insane format + } + len <<= 8; + len |= get8(s); + if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = get8(s); + if (count > 128) { + // Run + value = get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = get8(s); + } + } + } + for (i=0; i < width; ++i) + hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + free(scanline); + } + + return hdr_data; +} + +#ifndef STBI_NO_STDIO +float *stbi_hdr_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return hdr_load(&s,x,y,comp,req_comp); +} +#endif + +float *stbi_hdr_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer, len); + return hdr_load(&s,x,y,comp,req_comp); +} + +#endif // STBI_NO_HDR + +/////////////////////// write image /////////////////////// + +#ifndef STBI_NO_WRITE + +static void write8(FILE *f, int x) { uint8 z = (uint8) x; fwrite(&z,1,1,f); } + +static void writefv(FILE *f, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { uint8 x = va_arg(v, int); write8(f,x); break; } + case '2': { int16 x = va_arg(v, int); write8(f,x); write8(f,x>>8); break; } + case '4': { int32 x = va_arg(v, int); write8(f,x); write8(f,x>>8); write8(f,x>>16); write8(f,x>>24); break; } + default: + assert(0); + va_end(v); + return; + } + } +} + +static void writef(FILE *f, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + writefv(f,fmt,v); + va_end(v); +} + +static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad) +{ + uint8 bg[3] = { 255, 0, 255}, px[3]; + uint32 zero = 0; + int i,j,k, j_end; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + uint8 *d = (uint8 *) data + (j*x+i)*comp; + if (write_alpha < 0) + fwrite(&d[comp-1], 1, 1, f); + switch (comp) { + case 1: + case 2: writef(f, "111", d[0],d[0],d[0]); + break; + case 4: + if (!write_alpha) { + for (k=0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; + writef(f, "111", px[1-rgb_dir],px[1],px[1+rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + writef(f, "111", d[1-rgb_dir],d[1],d[1+rgb_dir]); + break; + } + if (write_alpha > 0) + fwrite(&d[comp-1], 1, 1, f); + } + fwrite(&zero,scanline_pad,1,f); + } +} + +static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...) +{ + FILE *f = fopen(filename, "wb"); + if (f) { + va_list v; + va_start(v, fmt); + writefv(f, fmt, v); + va_end(v); + write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad); + fclose(f); + } + return f != NULL; +} + +int stbi_write_bmp(char const *filename, int x, int y, int comp, void *data) +{ + int pad = (-x*3) & 3; + return outfile(filename,-1,-1,x,y,comp,data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +int stbi_write_tga(char const *filename, int x, int y, int comp, void *data) +{ + int has_alpha = !(comp & 1); + return outfile(filename, -1,-1, x, y, comp, data, has_alpha, 0, + "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); +} + +// any other image formats that do interleaved rgb data? +// PNG: requires adler32,crc32 -- significant amount of code +// PSD: no, channels output separately +// TIFF: no, stripwise-interleaved... i think + +#endif // STBI_NO_WRITE + +#endif // STBI_HEADER_FILE_ONLY + diff --git a/RecastDemo/Include/Filelist.h b/RecastDemo/Include/Filelist.h new file mode 100644 index 0000000..63c85b1 --- /dev/null +++ b/RecastDemo/Include/Filelist.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without 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 FILELIST_H +#define FILELIST_H + +struct FileList +{ + static const int MAX_FILES = 256; + + FileList(); + ~FileList(); + + char* files[MAX_FILES]; + int size; +}; + +void scanDirectory(const char* path, const char* ext, FileList& list); + +#endif // FILELIST_H diff --git a/RecastDemo/Include/SlideShow.h b/RecastDemo/Include/SlideShow.h new file mode 100644 index 0000000..c2f5d16 --- /dev/null +++ b/RecastDemo/Include/SlideShow.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without 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 SLIDESHOW_H +#define SLIDESHOW_H + +#include "Filelist.h" + +class SlideShow +{ + FileList m_files; + char m_path[256]; + + int m_width; + int m_height; + unsigned int m_texId; + + void purgeImage(); + bool loadImage(const char* path); + + bool m_showSlides; + bool m_showCurSlide; + float m_slideAlpha; + int m_curSlide; + int m_nextSlide; + +public: + SlideShow(); + ~SlideShow(); + + bool init(const char* path); + void nextSlide(); + void prevSlide(); + void setSlide(int n); + void updateAndDraw(float dt, const float w, const float h); +}; + +#endif // SLIDESHOW_H diff --git a/RecastDemo/Source/Filelist.cpp b/RecastDemo/Source/Filelist.cpp new file mode 100644 index 0000000..a9d3f3c --- /dev/null +++ b/RecastDemo/Source/Filelist.cpp @@ -0,0 +1,100 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without 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 "Filelist.h" +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif + +static void fileListAdd(FileList& list, const char* path) +{ + if (list.size >= FileList::MAX_FILES) + return; + int n = strlen(path); + list.files[list.size] = new char[n+1]; + strcpy(list.files[list.size], path); + list.size++; +} + +static void fileListClear(FileList& list) +{ + for (int i = 0; i < list.size; ++i) + delete [] list.files[i]; + list.size = 0; +} + +FileList::FileList() : size(0) +{ + memset(files, 0, sizeof(char*)*MAX_FILES); +} + +FileList::~FileList() +{ + fileListClear(*this); +} + +static int cmp(const void* a, const void* b) +{ + return strcmp(*(const char**)a, *(const char**)b); +} + +void scanDirectory(const char* path, const char* ext, FileList& list) +{ + fileListClear(list); + +#ifdef WIN32 + _finddata_t dir; + char pathWithExt[MAX_PATH]; + long fh; + strcpy(pathWithExt, path); + strcat(pathWithExt, "/*"); + strcat(pathWithExt, ext); + fh = _findfirst(pathWithExt, &dir); + if (fh == -1L) + return; + do + { + fileListAdd(list, dir.name); + } + while (_findnext(fh, &dir) == 0); + _findclose(fh); +#else + dirent* current = 0; + DIR* dp = opendir(path); + if (!dp) + return; + + while ((current = readdir(dp)) != 0) + { + int len = strlen(current->d_name); + if (len > 4 && strncmp(current->d_name+len-4, ext, 4) == 0) + { + fileListAdd(list, current->d_name); + } + } + closedir(dp); +#endif + + if (list.size > 1) + qsort(list.files, list.size, sizeof(char*), cmp); +} diff --git a/RecastDemo/Source/SlideShow.cpp b/RecastDemo/Source/SlideShow.cpp new file mode 100644 index 0000000..cbf78ed --- /dev/null +++ b/RecastDemo/Source/SlideShow.cpp @@ -0,0 +1,159 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without 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 "SlideShow.h" +#include +#include +#include +//#define STBI_HEADER_FILE_ONLY +#include "stb_image.h" + +SlideShow::SlideShow() : + m_width(0), + m_height(0), + m_texId(0), + m_showCurSlide(true), + m_slideAlpha(1.0f), + m_curSlide(-1), + m_nextSlide(0) +{ +} + +SlideShow::~SlideShow() +{ + purgeImage(); +} + +void SlideShow::purgeImage() +{ + if (m_texId) + { + glDeleteTextures(1, (GLuint*)&m_texId); + m_texId = 0; + m_width = 0; + m_height = 0; + } +} + +bool SlideShow::loadImage(const char* path) +{ + purgeImage(); + + int bpp; + unsigned char* data = stbi_load(path, &m_width, &m_height, &bpp, 4); + if (!data) + { + printf("Could not load file '%s': %s\n", path, stbi_failure_reason()); + return false; + } + + glGenTextures(1, (GLuint*)&m_texId); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_texId); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, m_width, m_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + stbi_image_free(data); + + return true; +} + +bool SlideShow::init(const char* path) +{ + strcpy(m_path, path); + scanDirectory(m_path, ".png", m_files); + + return true; +} + +void SlideShow::nextSlide() +{ + setSlide(m_nextSlide+1); +} + +void SlideShow::prevSlide() +{ + setSlide(m_nextSlide-1); +} + +void SlideShow::setSlide(int n) +{ + const int maxIdx = m_files.size ? m_files.size-1 : 0; + m_nextSlide = n; + if (m_nextSlide < 0) m_nextSlide = 0; + if (m_nextSlide > maxIdx) m_nextSlide = maxIdx; +} + +void SlideShow::updateAndDraw(float dt, const float w, const float h) +{ + float slideAlphaTarget = (m_showCurSlide && m_texId) ? 1 : 0; + if (m_curSlide != m_nextSlide) + slideAlphaTarget = 0; + + if (slideAlphaTarget > m_slideAlpha) + m_slideAlpha += dt*4; + else if (slideAlphaTarget < m_slideAlpha) + m_slideAlpha -= dt*4; + if (m_slideAlpha < 0) m_slideAlpha = 0; + if (m_slideAlpha > 1) m_slideAlpha = 1; + + if (m_curSlide != m_nextSlide && m_slideAlpha < 0.01f) + { + m_curSlide = m_nextSlide; + if (m_curSlide >= 0 && m_curSlide < m_files.size) + { + char path[256]; + strcpy(path, m_path); + strcat(path, m_files.files[m_curSlide]); + loadImage(path); + } + } + + if (m_slideAlpha > 0.01f && m_texId) + { + unsigned char alpha = (unsigned char)(m_slideAlpha*255.0f); + + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_texId); + + const float tw = m_width; + const float th = m_height; + const float hw = tw/2; //w*0.5f; + const float hh = th/2; //h*0.5f; + + glColor4ub(255,255,255,alpha); + glBegin(GL_QUADS); + glTexCoord2f(0,th); + glVertex2f(hw-tw/2,hh-th/2); + glTexCoord2f(tw,th); + glVertex2f(hw+tw/2,hh-th/2); + glTexCoord2f(tw,0); + glVertex2f(hw+tw/2,hh+th/2); + glTexCoord2f(0,0); + glVertex2f(hw-tw/2,hh+th/2); + glEnd(); + + glDisable(GL_TEXTURE_RECTANGLE_ARB); + } + +} diff --git a/RecastDemo/Source/main.cpp b/RecastDemo/Source/main.cpp index e33cf15..8575e36 100644 --- a/RecastDemo/Source/main.cpp +++ b/RecastDemo/Source/main.cpp @@ -19,12 +19,6 @@ #include #define _USE_MATH_DEFINES #include -#ifdef WIN32 -# include -#else -# include -#endif - #include "SDL.h" #include "SDL_opengl.h" #include "imgui.h" @@ -33,6 +27,8 @@ #include "RecastDebugDraw.h" #include "InputGeom.h" #include "TestCase.h" +#include "Filelist.h" +#include "SlideShow.h" #include "Sample_SoloMeshSimple.h" #include "Sample_SoloMeshTiled.h" @@ -43,91 +39,6 @@ # define snprintf _snprintf #endif - -struct FileList -{ - static const int MAX_FILES = 256; - inline FileList() : size(0) - { - memset(files, 0, sizeof(char*)*MAX_FILES); - } - - inline ~FileList() - { - clear(); - } - - void clear() - { - for (int i = 0; i < size; ++i) - delete [] files[i]; - size = 0; - } - - void add(const char* path) - { - if (size >= MAX_FILES) - return; - int n = strlen(path); - files[size] = new char[n+1]; - strcpy(files[size], path); - size++; - } - - static int cmp(const void* a, const void* b) - { - return strcmp(*(const char**)a, *(const char**)b); - } - - void sort() - { - if (size > 1) - qsort(files, size, sizeof(char*), cmp); - } - - char* files[MAX_FILES]; - int size; -}; - -static void scanDirectory(const char* path, const char* ext, FileList& list) -{ - list.clear(); - -#ifdef WIN32 - _finddata_t dir; - char pathWithExt[MAX_PATH]; - long fh; - strcpy(pathWithExt, path); - strcat(pathWithExt, "/*"); - strcat(pathWithExt, ext); - fh = _findfirst(pathWithExt, &dir); - if (fh == -1L) - return; - do - { - list.add(dir.name); - } - while (_findnext(fh, &dir) == 0); - _findclose(fh); -#else - dirent* current = 0; - DIR* dp = opendir(path); - if (!dp) - return; - - while ((current = readdir(dp)) != 0) - { - int len = strlen(current->d_name); - if (len > 4 && strncmp(current->d_name+len-4, ext, 4) == 0) - { - list.add(current->d_name); - } - } - closedir(dp); -#endif - list.sort(); -} - struct SampleItem { Sample* (*create)(); @@ -219,6 +130,9 @@ int main(int /*argc*/, char** /*argv*/) float mpos[3] = {0,0,0}; bool mposSet = false; + SlideShow slideShow; + slideShow.init("slides/"); + InputGeom* geom = 0; Sample* sample = 0; TestCase* test = 0; @@ -257,13 +171,17 @@ int main(int /*argc*/, char** /*argv*/) { done = true; } - else if (event.key.keysym.sym == SDLK_TAB) + else if (event.key.keysym.sym == SDLK_t) { showLevels = false; showSample = false; showTestCases = true; scanDirectory("Tests", ".txt", files); } + else if (event.key.keysym.sym == SDLK_TAB) + { + showMenu = !showMenu; + } else if (event.key.keysym.sym == SDLK_SPACE) { if (sample) @@ -325,6 +243,14 @@ int main(int /*argc*/, char** /*argv*/) glFogf(GL_FOG_END, camr*1.25f); } } + else if (event.key.keysym.sym == SDLK_RIGHT) + { + slideShow.nextSlide(); + } + else if (event.key.keysym.sym == SDLK_LEFT) + { + slideShow.prevSlide(); + } break; case SDL_MOUSEBUTTONDOWN: @@ -899,6 +825,8 @@ int main(int /*argc*/, char** /*argv*/) imguiEndScrollArea(); } + slideShow.updateAndDraw(dt, width, height); + // Marker if (mposSet && gluProject((GLdouble)mpos[0], (GLdouble)mpos[1], (GLdouble)mpos[2], model, proj, view, &x, &y, &z))